From 8d370ce59836c2b84d15e72655aa9202feda0581 Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Mon, 2 Mar 2026 10:04:27 +0000 Subject: [PATCH 001/170] 8377937: [macos] GlyphMetrics advance does not consider font rotation Reviewed-by: prr, serb, psadhukhan --- .../macosx/classes/sun/font/CStrike.java | 16 +++- .../GlyphMetricsRotatedFontTest.java | 80 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 test/jdk/java/awt/font/GlyphVector/GlyphMetricsRotatedFontTest.java diff --git a/src/java.desktop/macosx/classes/sun/font/CStrike.java b/src/java.desktop/macosx/classes/sun/font/CStrike.java index bffb76fb1ad..f7fa00070ff 100644 --- a/src/java.desktop/macosx/classes/sun/font/CStrike.java +++ b/src/java.desktop/macosx/classes/sun/font/CStrike.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -174,7 +174,19 @@ public final class CStrike extends PhysicalStrike { @Override Point2D.Float getGlyphMetrics(final int glyphCode) { - return new Point2D.Float(getGlyphAdvance(glyphCode), 0.0f); + Point2D.Float metrics = new Point2D.Float(); + long glyphPtr = getGlyphImagePtr(glyphCode); + if (glyphPtr != 0L) { + metrics.x = StrikeCache.getGlyphXAdvance(glyphPtr); + metrics.y = StrikeCache.getGlyphYAdvance(glyphPtr); + /* advance is currently in device space, need to convert back + * into user space. + * This must not include the translation component. */ + if (invDevTx != null) { + invDevTx.deltaTransform(metrics, metrics); + } + } + return metrics; } @Override diff --git a/test/jdk/java/awt/font/GlyphVector/GlyphMetricsRotatedFontTest.java b/test/jdk/java/awt/font/GlyphVector/GlyphMetricsRotatedFontTest.java new file mode 100644 index 00000000000..eb00fd4f34d --- /dev/null +++ b/test/jdk/java/awt/font/GlyphVector/GlyphMetricsRotatedFontTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8148334 8377937 + * @summary Checks behavior of GlyphVector.getGlyphMetrics(int) with rotated fonts. + */ + +import java.awt.Font; +import java.awt.GraphicsEnvironment; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; + +public class GlyphMetricsRotatedFontTest { + + public static void main(String[] args) { + + String text = "The quick brown \r\n fox JUMPS over \t the lazy dog."; + FontRenderContext frc = new FontRenderContext(null, true, true); + + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + String[] names = ge.getAvailableFontFamilyNames(); + + for (String name : names) { + + Font normal = new Font(name, Font.PLAIN, 60); + if (normal.canDisplayUpTo("AZaz09") != -1) { + continue; + } + + double theta = 0.5; // about 30 degrees + AffineTransform tx = AffineTransform.getRotateInstance(theta); + Font rotated = normal.deriveFont(tx); + + GlyphVector gv1 = normal.createGlyphVector(frc, text); + GlyphVector gv2 = rotated.createGlyphVector(frc, text); + + for (int i = 0; i < gv1.getNumGlyphs(); i++) { + GlyphMetrics gm1 = gv1.getGlyphMetrics(i); + GlyphMetrics gm2 = gv2.getGlyphMetrics(i); + assertEqual(0, gm1.getAdvanceY(), 0, name + " normal y", i); + double expectedX = Math.cos(theta) * gm1.getAdvanceX(); + double expectedY = Math.sin(theta) * gm1.getAdvanceX(); + assertEqual(expectedX, gm2.getAdvanceX(), 1, name + " rotated x", i); + assertEqual(expectedY, gm2.getAdvanceY(), 1, name + " rotated y", i); + } + } + } + + private static void assertEqual(double d1, double d2, double variance, + String scenario, int index) { + if (Math.abs(d1 - d2) > variance) { + String msg = String.format("%s for index %d: %f != %f", scenario, index, d1, d2); + throw new RuntimeException(msg); + } + } +} From b12daa41e23eaac2777a8f89ef279963d0e6f7a0 Mon Sep 17 00:00:00 2001 From: Oli Gillespie Date: Mon, 2 Mar 2026 10:16:57 +0000 Subject: [PATCH 002/170] 8378110: Add -XX: prefix to settings-file flags in RuntimeMXBean.getInputArguments() Reviewed-by: kevinw, dholmes --- src/hotspot/share/prims/jvm.cpp | 4 +- .../RuntimeMXBean/InputArgument.java | 53 +++++++++++++------ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 2b3a2966c27..423e1a5a1f4 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3641,7 +3641,9 @@ JVM_ENTRY(jobjectArray, JVM_GetVmArguments(JNIEnv *env)) int index = 0; for (int j = 0; j < num_flags; j++, index++) { - Handle h = java_lang_String::create_from_platform_dependent_str(vm_flags[j], CHECK_NULL); + stringStream prefixed; + prefixed.print("-XX:%s", vm_flags[j]); + Handle h = java_lang_String::create_from_platform_dependent_str(prefixed.base(), CHECK_NULL); result_h->obj_at_put(index, h()); } for (int i = 0; i < num_args; i++, index++) { diff --git a/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java b/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java index 66c3d3f41f5..0e7609b86ed 100644 --- a/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java +++ b/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,41 +62,60 @@ * @run main/othervm -Dprops=something InputArgument -Dprops=something */ +/* + * @test + * @bug 8378110 + * @summary RuntimeMXBean.getInputArguments() handling of flags from settings file. + * + * @run driver InputArgument generateFlagsFile + * @run main/othervm -XX:+UseFastJNIAccessors -XX:Flags=InputArgument.flags InputArgument + * -XX:+UseFastJNIAccessors -XX:-UseG1GC -XX:+UseParallelGC -XX:MaxHeapSize=100M + */ + import java.lang.management.*; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.List; import java.util.ListIterator; public class InputArgument { private static RuntimeMXBean rm = ManagementFactory.getRuntimeMXBean(); - private static String vmOption = null; public static void main(String args[]) throws Exception { - // set the expected input argument - if (args.length > 0) { - vmOption = args[0]; - } - - List options = rm.getInputArguments(); - if (vmOption == null) { + if (args.length == 1 && "generateFlagsFile".equals(args[0])) { + generateFlagsFile(); return; } - boolean testFailed = true; + String[] vmOptions = args; + List options = rm.getInputArguments(); System.out.println("Number of arguments = " + options.size()); int i = 0; for (String arg : options) { System.out.println("Input arg " + i + " = " + arg); i++; - if (arg.equals(vmOption)) { - testFailed = false; - break; - } } - if (testFailed) { - throw new RuntimeException("TEST FAILED: " + - "VM option " + vmOption + " not found"); + + for (String expected : vmOptions) { + boolean found = false; + for (String arg : options) { + if (arg.equals(expected)) { + found = true; + break; + } + } + if (!found) { + throw new RuntimeException("TEST FAILED: " + + "VM option " + expected + " not found"); + } } System.out.println("Test passed."); } + + private static void generateFlagsFile() throws Exception { + // 3 types of flag; both boolean cases and 1 numeric + Files.writeString(Paths.get("", "InputArgument.flags"), + String.format("-UseG1GC%n+UseParallelGC%nMaxHeapSize=100M%n")); + } } From b7d0cb5fb36965874f0950ab882dc517b002509f Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Mon, 2 Mar 2026 12:49:01 +0000 Subject: [PATCH 003/170] 8378888: jdk/incubator/vector/Float16OperationsBenchmark.java uses wrong package name Reviewed-by: jiefu, jbhateja, syan, liach --- .../bench/jdk/incubator/vector/Float16OperationsBenchmark.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java index ebbfbb01cc6..cbfe9958924 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/Float16OperationsBenchmark.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.openjdk.bench.java.lang; +package org.openjdk.bench.jdk.incubator.vector; import java.util.stream.IntStream; import java.util.concurrent.TimeUnit; From 29a40c3c6821da3d40c3aa45a0650e8d0ad5255d Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 2 Mar 2026 13:39:44 +0000 Subject: [PATCH 004/170] 8378793: Add ResolvedFieldEntry is_valid assert Reviewed-by: dholmes, dsimms, matsaave --- .../share/interpreter/interpreterRuntime.cpp | 12 +++---- src/hotspot/share/oops/resolvedFieldEntry.cpp | 34 ++++++++++++++++++- src/hotspot/share/oops/resolvedFieldEntry.hpp | 24 ++++++------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index ca7174389cf..e3cf5d589c2 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -711,9 +711,7 @@ void InterpreterRuntime::resolve_get_put(Bytecodes::Code bytecode, int field_ind } ResolvedFieldEntry* entry = pool->resolved_field_entry_at(field_index); - entry->set_flags(info.access_flags().is_final(), info.access_flags().is_volatile()); - entry->fill_in(info.field_holder(), info.offset(), - checked_cast(info.index()), checked_cast(state), + entry->fill_in(info, checked_cast(state), static_cast(get_code), static_cast(put_code)); } @@ -1189,10 +1187,9 @@ JRT_LEAF(void, InterpreterRuntime::at_unwind(JavaThread* current)) JRT_END JRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread* current, oopDesc* obj, - ResolvedFieldEntry *entry)) + ResolvedFieldEntry* entry)) // check the access_flags for the field in the klass - InstanceKlass* ik = entry->field_holder(); int index = entry->field_index(); if (!ik->field_status(index).is_access_watched()) return; @@ -1212,11 +1209,10 @@ JRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread* current, oopDe JRT_END JRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread* current, oopDesc* obj, - ResolvedFieldEntry *entry, jvalue *value)) - - InstanceKlass* ik = entry->field_holder(); + ResolvedFieldEntry* entry, jvalue* value)) // check the access_flags for the field in the klass + InstanceKlass* ik = entry->field_holder(); int index = entry->field_index(); // bail out if field modifications are not watched if (!ik->field_status(index).is_modification_watched()) return; diff --git a/src/hotspot/share/oops/resolvedFieldEntry.cpp b/src/hotspot/share/oops/resolvedFieldEntry.cpp index 83f1a6919a6..49e9115ca9a 100644 --- a/src/hotspot/share/oops/resolvedFieldEntry.cpp +++ b/src/hotspot/share/oops/resolvedFieldEntry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,12 @@ #include "cds/archiveBuilder.hpp" #include "cppstdlib/type_traits.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/instanceOop.hpp" #include "oops/resolvedFieldEntry.hpp" +#include "runtime/fieldDescriptor.inline.hpp" +#include "utilities/checkedCast.hpp" +#include "utilities/globalDefinitions.hpp" static_assert(std::is_trivially_copyable_v); @@ -34,6 +39,19 @@ class ResolvedFieldEntryWithExtra : public ResolvedFieldEntry { }; static_assert(sizeof(ResolvedFieldEntryWithExtra) > sizeof(ResolvedFieldEntry)); +void ResolvedFieldEntry::fill_in(const fieldDescriptor& info, u1 tos_state, u1 get_code, u1 put_code) { + set_flags(info.access_flags().is_final(), info.access_flags().is_volatile()); + _field_holder = info.field_holder(); + _field_offset = info.offset(); + _field_index = checked_cast(info.index()); + _tos_state = tos_state; + + // These must be set after the other fields + set_bytecode(&_get_code, get_code); + set_bytecode(&_put_code, put_code); + assert_is_valid(); +} + void ResolvedFieldEntry::print_on(outputStream* st) const { st->print_cr("Field Entry:"); @@ -52,6 +70,20 @@ void ResolvedFieldEntry::print_on(outputStream* st) const { st->print_cr(" - Put Bytecode: %s", Bytecodes::name((Bytecodes::Code)put_code())); } +#ifdef ASSERT +void ResolvedFieldEntry::assert_is_valid() const { + assert(field_holder()->is_instance_klass(), "should be instanceKlass"); + assert(field_offset() >= instanceOopDesc::base_offset_in_bytes(), + "field offset out of range %d >= %d", field_offset(), instanceOopDesc::base_offset_in_bytes()); + assert(as_BasicType((TosState)tos_state()) != T_ILLEGAL, "tos_state is ILLEGAL"); + assert(_flags < (1 << (max_flag_shift + 1)), "flags are too large %d", _flags); + assert((get_code() == 0 || get_code() == Bytecodes::_getstatic || get_code() == Bytecodes::_getfield), + "invalid get bytecode %d", get_code()); + assert((put_code() == 0 || put_code() == Bytecodes::_putstatic || put_code() == Bytecodes::_putfield), + "invalid put bytecode %d", put_code()); +} +#endif + #if INCLUDE_CDS void ResolvedFieldEntry::remove_unshareable_info() { *this = ResolvedFieldEntry(_cpool_index); diff --git a/src/hotspot/share/oops/resolvedFieldEntry.hpp b/src/hotspot/share/oops/resolvedFieldEntry.hpp index 77ad4815730..bdd9999dd63 100644 --- a/src/hotspot/share/oops/resolvedFieldEntry.hpp +++ b/src/hotspot/share/oops/resolvedFieldEntry.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ #define SHARE_OOPS_RESOLVEDFIELDENTRY_HPP #include "interpreter/bytecodes.hpp" -#include "oops/instanceKlass.hpp" #include "runtime/atomicAccess.hpp" #include "utilities/checkedCast.hpp" #include "utilities/sizes.hpp" @@ -46,7 +45,8 @@ // The explicit paddings are necessary for generating deterministic CDS archives. They prevent // the C++ compiler from potentially inserting random values in unused gaps. -//class InstanceKlass; +class InstanceKlass; + class ResolvedFieldEntry { friend class VMStructs; @@ -84,6 +84,7 @@ public: enum { is_volatile_shift = 0, is_final_shift = 1, // unused + max_flag_shift = is_final_shift }; // Getters @@ -113,6 +114,7 @@ public: // Printing void print_on(outputStream* st) const; + private: void set_flags(bool is_final_flag, bool is_volatile_flag) { int new_flags = (is_final_flag << is_final_shift) | static_cast(is_volatile_flag); _flags = checked_cast(new_flags); @@ -129,17 +131,12 @@ public: AtomicAccess::release_store(code, new_code); } - // Populate the strucutre with resolution information - void fill_in(InstanceKlass* klass, int offset, u2 index, u1 tos_state, u1 b1, u1 b2) { - _field_holder = klass; - _field_offset = offset; - _field_index = index; - _tos_state = tos_state; + // Debug help + void assert_is_valid() const NOT_DEBUG_RETURN; - // These must be set after the other fields - set_bytecode(&_get_code, b1); - set_bytecode(&_put_code, b2); - } + public: + // Populate the strucutre with resolution information + void fill_in(const fieldDescriptor& info, u1 tos_state, u1 get_code, u1 put_code); // CDS #if INCLUDE_CDS @@ -155,7 +152,6 @@ public: static ByteSize put_code_offset() { return byte_offset_of(ResolvedFieldEntry, _put_code); } static ByteSize type_offset() { return byte_offset_of(ResolvedFieldEntry, _tos_state); } static ByteSize flags_offset() { return byte_offset_of(ResolvedFieldEntry, _flags); } - }; #endif //SHARE_OOPS_RESOLVEDFIELDENTRY_HPP From 373ad02d3a1fefcd3e1b3b90f594ab7a2cacfd9f Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Mon, 2 Mar 2026 14:12:33 +0000 Subject: [PATCH 005/170] 8378786: PeerConnectionId::cloneBuffer should use absolute bulk get Reviewed-by: vyazici, djelinski --- .../internal/net/http/quic/PeerConnectionId.java | 9 +++++++-- .../net/http/quic/QuicConnectionImpl.java | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnectionId.java b/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnectionId.java index 0c6f946d1a2..b822480c2a5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnectionId.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnectionId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,8 +72,13 @@ public final class PeerConnectionId extends QuicConnectionId { } private static ByteBuffer cloneBuffer(ByteBuffer src) { + // we make a copy of the bytes and create a new + // ByteBuffer here because we do not want to retain + // the memory that was allocated for the original + // ByteBuffer, which could ba a slice of a larger + // buffer, such as the whole datagram payload. final byte[] idBytes = new byte[src.remaining()]; - src.get(idBytes); + src.get(src.position(), idBytes); return ByteBuffer.wrap(idBytes); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java index edb94d5929a..41b814a551c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java @@ -703,7 +703,9 @@ public class QuicConnectionImpl extends QuicConnection implements QuicPacketRece return; } if (debug.on()) { - debug.log("scheduleForDecryption: %d bytes", received); + debug.log("scheduleForDecryption: %s bytes [idbytes: %s(%s,%s)]", + received, datagram.destConnId().getClass().getSimpleName(), + datagram.destConnId().position(), datagram.destConnId().limit()); } endpoint.buffer(received); incoming.add(datagram); @@ -1847,6 +1849,10 @@ public class QuicConnectionImpl extends QuicConnection implements QuicPacketRece header.destinationId().toHexString(), Utils.asHexString(destConnId)); } + assert packetIndex > 1 : + "first long packet CID does not match itself %s(%s,%s)" + .formatted(destConnId.getClass().getSimpleName(), + destConnId.position(), destConnId.limit()); return; } var peekedVersion = header.version(); @@ -1918,6 +1924,10 @@ public class QuicConnectionImpl extends QuicConnection implements QuicPacketRece " wrong connection id (%s vs %s)", packetIndex, Utils.asHexString(cid), Utils.asHexString(destConnId)); } + assert packetIndex > 1 : "first short packet CID does not match itself %s(%s,%s)" + .formatted(destConnId.getClass().getSimpleName(), + destConnId.position(), destConnId.limit()); + return; } @@ -1934,6 +1944,9 @@ public class QuicConnectionImpl extends QuicConnection implements QuicPacketRece if (debug.on()) { debug.log("Failed to process incoming packet", t); } + if (t instanceof AssertionError) { + this.terminator.terminate(TerminationCause.forException(t)); + } } } From 2c3e4f08fa3f15fa37b59dff89b6039ac1051a6d Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Mon, 2 Mar 2026 14:13:19 +0000 Subject: [PATCH 006/170] 8378595: Refactor miscellaneous tests under test/jdk/java/net/httpclient from TestNG to JUnit Reviewed-by: syan, vyazici --- .../BufferingSubscriberCancelTest.java | 2 +- .../BodyHandlerOfFileDownloadTest.java | 74 ++++++++++--------- .../PathSubscriber/BodyHandlerOfFileTest.java | 70 +++++++++--------- .../BodySubscriberOfFileTest.java | 73 +++++++++--------- .../httpclient/offline/OfflineTesting.java | 34 +++++---- .../FileProcessorPermissionTest.java | 8 +- .../filePerms/SecurityBeforeFile.java | 18 +++-- 7 files changed, 148 insertions(+), 131 deletions(-) diff --git a/test/jdk/java/net/httpclient/BufferingSubscriberCancelTest.java b/test/jdk/java/net/httpclient/BufferingSubscriberCancelTest.java index 7813b8c3d7b..4d73ec31280 100644 --- a/test/jdk/java/net/httpclient/BufferingSubscriberCancelTest.java +++ b/test/jdk/java/net/httpclient/BufferingSubscriberCancelTest.java @@ -214,6 +214,6 @@ public class BufferingSubscriberCancelTest { return; Thread.sleep(100); } - assertEquals(expected, actual); // will fail with the usual testng message + assertEquals(expected, actual); // will fail with the usual junit message } } diff --git a/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileDownloadTest.java b/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileDownloadTest.java index eb397d37b7a..92d359e32c6 100644 --- a/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileDownloadTest.java +++ b/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileDownloadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,15 +37,11 @@ * jdk.test.lib.net.SimpleSSLContext * jdk.test.lib.Platform * jdk.test.lib.util.FileUtils - * @run testng/othervm BodyHandlerOfFileDownloadTest + * @run junit/othervm BodyHandlerOfFileDownloadTest */ import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.util.FileUtils; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -73,28 +69,35 @@ import static java.net.http.HttpOption.H3_DISCOVERY; import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.WRITE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class BodyHandlerOfFileDownloadTest implements HttpServerAdapters { static final String MSG = "msg"; static final String contentDispositionValue = "attachment; filename=example.html"; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 [ 5 servers ] - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - String http3URI; + private static HttpTestServer httpTestServer; // HTTP/1.1 [ 5 servers ] + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String http3URI; - FileSystem zipFs; - Path defaultFsPath; - Path zipFsPath; + private static FileSystem zipFs; + private static Path defaultFsPath; + private static Path zipFsPath; // Default file system @@ -106,12 +109,10 @@ public class BodyHandlerOfFileDownloadTest implements HttpServerAdapters { return dir; } - @DataProvider(name = "defaultFsData") - public Object[][] defaultFsData() { + public static Object[][] defaultFsData() { return new Object[][]{ { http3URI, defaultFsPath, MSG, true }, { http3URI, defaultFsPath, MSG, false }, - { httpURI, defaultFsPath, MSG, true }, { httpsURI, defaultFsPath, MSG, true }, { http2URI, defaultFsPath, MSG, true }, @@ -123,7 +124,8 @@ public class BodyHandlerOfFileDownloadTest implements HttpServerAdapters { }; } - @Test(dataProvider = "defaultFsData") + @ParameterizedTest + @MethodSource("defaultFsData") public void testDefaultFs(String uriString, Path path, String expectedMsg, @@ -171,10 +173,10 @@ public class BodyHandlerOfFileDownloadTest implements HttpServerAdapters { out.printf("Resp code: %s\n", resp.statusCode()); out.println("Resp body Path: " + resp.body()); out.printf("Resp body written to file: %s\n", msg); - assertEquals(resp.statusCode(), 200); - assertEquals(msg, expectedMsg); + assertEquals(200, resp.statusCode()); + assertEquals(expectedMsg, msg); assertTrue(resp.headers().firstValue("Content-Disposition").isPresent()); - assertEquals(resp.headers().firstValue("Content-Disposition").get(), contentDispositionValue); + assertEquals(contentDispositionValue, resp.headers().firstValue("Content-Disposition").get()); if (!sameClient) { client.close(); } @@ -199,15 +201,17 @@ public class BodyHandlerOfFileDownloadTest implements HttpServerAdapters { return dir; } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testZipFs() { - out.printf("\n\n--- testZipFs(): starting\n"); - BodyHandlers.ofFileDownload(zipFsPath, CREATE, TRUNCATE_EXISTING, WRITE); + Assertions.assertThrows(IllegalArgumentException.class, () -> { + out.printf("\n\n--- testZipFs(): starting\n"); + BodyHandlers.ofFileDownload(zipFsPath, CREATE, TRUNCATE_EXISTING, WRITE); + }); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { defaultFsPath = defaultFsDir(); zipFs = newZipFs(); zipFsPath = zipFsDir(zipFs); @@ -239,8 +243,8 @@ public class BodyHandlerOfFileDownloadTest implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { if (Files.exists(zipFsPath)) FileUtils.deleteFileTreeWithRetry(zipFsPath); if (Files.exists(defaultFsPath)) diff --git a/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileTest.java b/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileTest.java index 13871933eac..53b8607f294 100644 --- a/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileTest.java +++ b/test/jdk/java/net/httpclient/PathSubscriber/BodyHandlerOfFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,15 +36,11 @@ * jdk.httpclient.test.lib.http2.Queue * jdk.test.lib.net.SimpleSSLContext * jdk.test.lib.Platform jdk.test.lib.util.FileUtils - * @run testng/othervm BodyHandlerOfFileTest + * @run junit/othervm BodyHandlerOfFileTest */ import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.util.FileUtils; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -56,7 +52,10 @@ import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; -import java.nio.file.*; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Map; import jdk.httpclient.test.lib.common.HttpServerAdapters; import static java.lang.System.out; @@ -66,26 +65,31 @@ import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; public class BodyHandlerOfFileTest implements HttpServerAdapters { static final String MSG = "msg"; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 [ 5 servers ] - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - String http3URI; + private static HttpTestServer httpTestServer; // HTTP/1.1 [ 5 servers ] + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String http3URI; - FileSystem zipFs; - Path defaultFsPath; - Path zipFsPath; + private static FileSystem zipFs; + private static Path defaultFsPath; + private static Path zipFsPath; // Default file system set-up @@ -97,8 +101,7 @@ public class BodyHandlerOfFileTest implements HttpServerAdapters { return file; } - @DataProvider(name = "defaultFsData") - public Object[][] defaultFsData() { + public static Object[][] defaultFsData() { return new Object[][]{ { http3URI, defaultFsPath, MSG, true }, { http3URI, defaultFsPath, MSG, false }, @@ -114,7 +117,8 @@ public class BodyHandlerOfFileTest implements HttpServerAdapters { }; } - @Test(dataProvider = "defaultFsData") + @ParameterizedTest + @MethodSource("defaultFsData") public void testDefaultFs(String uriString, Path path, String expectedMsg, @@ -139,8 +143,7 @@ public class BodyHandlerOfFileTest implements HttpServerAdapters { return file; } - @DataProvider(name = "zipFsData") - public Object[][] zipFsData() { + public static Object[][] zipFsData() { return new Object[][]{ { http3URI, zipFsPath, MSG, true }, { http3URI, zipFsPath, MSG, false }, @@ -156,7 +159,8 @@ public class BodyHandlerOfFileTest implements HttpServerAdapters { }; } - @Test(dataProvider = "zipFsData") + @ParameterizedTest + @MethodSource("zipFsData") public void testZipFs(String uriString, Path path, String expectedMsg, @@ -203,8 +207,8 @@ public class BodyHandlerOfFileTest implements HttpServerAdapters { String msg = Files.readString(path, StandardCharsets.UTF_8); out.printf("Resp code: %s\n", resp.statusCode()); out.printf("Msg written to %s: %s\n", resp.body(), msg); - assertEquals(resp.statusCode(), 200); - assertEquals(msg, expectedMsg); + assertEquals(200, resp.statusCode()); + assertEquals(expectedMsg, msg); if (!sameClient) { client.close(); } @@ -214,8 +218,8 @@ public class BodyHandlerOfFileTest implements HttpServerAdapters { } } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { defaultFsPath = defaultFsFile(); zipFs = newZipFs(); zipFsPath = zipFsFile(zipFs); @@ -247,8 +251,8 @@ public class BodyHandlerOfFileTest implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { if (Files.exists(zipFsPath)) FileUtils.deleteFileTreeWithRetry(zipFsPath); if (Files.exists(defaultFsPath)) diff --git a/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java b/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java index d7c9a3af4f1..da0c7220b6b 100644 --- a/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java +++ b/test/jdk/java/net/httpclient/PathSubscriber/BodySubscriberOfFileTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,15 +35,11 @@ * jdk.httpclient.test.lib.http2.OutgoingPushPromise * jdk.httpclient.test.lib.http2.Queue jdk.test.lib.net.SimpleSSLContext * jdk.test.lib.Platform jdk.test.lib.util.FileUtils - * @run testng/othervm BodySubscriberOfFileTest + * @run junit/othervm BodySubscriberOfFileTest */ import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.util.FileUtils; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -58,7 +54,10 @@ import java.net.http.HttpResponse.BodySubscribers; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.nio.file.*; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Map; import java.util.concurrent.Flow; import java.util.stream.IntStream; @@ -70,26 +69,32 @@ import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; public class BodySubscriberOfFileTest implements HttpServerAdapters { static final String MSG = "msg"; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer httpTestServer; // HTTP/1.1 [ 5 servers ] - HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - HttpTestServer http3TestServer; // HTTP/3 ( h3 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - String http3URI; + private static HttpTestServer httpTestServer; // HTTP/1.1 [ 5 servers ] + private static HttpTestServer httpsTestServer; // HTTPS/1.1 + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 ) + private static String httpURI; + private static String httpsURI; + private static String http2URI; + private static String https2URI; + private static String http3URI; - FileSystem zipFs; - Path defaultFsPath; - Path zipFsPath; + private static FileSystem zipFs; + private static Path defaultFsPath; + private static Path zipFsPath; // Default file system set-up @@ -101,8 +106,7 @@ public class BodySubscriberOfFileTest implements HttpServerAdapters { return file; } - @DataProvider(name = "defaultFsData") - public Object[][] defaultFsData() { + public static Object[][] defaultFsData() { return new Object[][]{ { http3URI, defaultFsPath, MSG, true }, { http3URI, defaultFsPath, MSG, false }, @@ -118,7 +122,8 @@ public class BodySubscriberOfFileTest implements HttpServerAdapters { }; } - @Test(dataProvider = "defaultFsData") + @ParameterizedTest + @MethodSource("defaultFsData") public void testDefaultFs(String uriString, Path path, String expectedMsg, @@ -143,8 +148,7 @@ public class BodySubscriberOfFileTest implements HttpServerAdapters { return file; } - @DataProvider(name = "zipFsData") - public Object[][] zipFsData() { + public static Object[][] zipFsData() { return new Object[][]{ { http3URI, zipFsPath, MSG, true }, { http3URI, zipFsPath, MSG, false }, @@ -160,7 +164,8 @@ public class BodySubscriberOfFileTest implements HttpServerAdapters { }; } - @Test(dataProvider = "zipFsData") + @ParameterizedTest + @MethodSource("zipFsData") public void testZipFs(String uriString, Path path, String expectedMsg, @@ -209,8 +214,8 @@ public class BodySubscriberOfFileTest implements HttpServerAdapters { String msg = Files.readString(path, StandardCharsets.UTF_8); out.printf("Resp code: %s\n", resp.statusCode()); out.printf("Msg written to %s: %s\n", resp.body(), msg); - assertEquals(resp.statusCode(), 200); - assertEquals(msg, expectedMsg); + assertEquals(200, resp.statusCode()); + assertEquals(expectedMsg, msg); if (!sameClient) { client.close(); } @@ -240,12 +245,12 @@ public class BodySubscriberOfFileTest implements HttpServerAdapters { }); subscriber.onNext(buffers); subscriber.onComplete(); - buffers.forEach(b -> assertEquals(b.remaining(), 0) ); + buffers.forEach(b -> assertEquals(0, b.remaining()) ); assertEquals(expectedSize, Files.size(defaultFsPath)); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { defaultFsPath = defaultFsFile(); zipFs = newZipFs(); zipFsPath = zipFsFile(zipFs); @@ -277,8 +282,8 @@ public class BodySubscriberOfFileTest implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { if (Files.exists(zipFsPath)) FileUtils.deleteFileTreeWithRetry(zipFsPath); if (Files.exists(defaultFsPath)) diff --git a/test/jdk/java/net/httpclient/offline/OfflineTesting.java b/test/jdk/java/net/httpclient/offline/OfflineTesting.java index 2f4833bf179..f36a457022e 100644 --- a/test/jdk/java/net/httpclient/offline/OfflineTesting.java +++ b/test/jdk/java/net/httpclient/offline/OfflineTesting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @summary Demonstrates how to achieve testing without network connections * @build DelegatingHttpClient FixedHttpResponse FixedResponseHttpClient - * @run testng/othervm OfflineTesting + * @run junit/othervm OfflineTesting */ import java.io.IOException; @@ -40,13 +40,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.BiPredicate; -import org.testng.annotations.Test; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Objects.requireNonNull; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class OfflineTesting { @@ -72,9 +74,9 @@ public class OfflineTesting { client.sendAsync(request, BodyHandlers.ofString()) .thenAccept(response -> { System.out.println("response: " + response); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); assertTrue(response.headers().firstValue("Server").isPresent()); - assertEquals(response.body(), "A response message"); + assertEquals("A response message", response.body()); }) .join(); } @@ -91,9 +93,9 @@ public class OfflineTesting { client.sendAsync(request, BodyHandlers.ofByteArray()) .thenAccept(response -> { System.out.println("response: " + response); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); assertTrue(response.headers().firstValue("Content-Type").isPresent()); - assertEquals(response.body(), "A response message".getBytes(UTF_8)); + Assertions.assertArrayEquals("A response message".getBytes(UTF_8), response.body()); }) .join(); } @@ -125,9 +127,9 @@ public class OfflineTesting { try (var client = fixedClient) { client.sendAsync(request, BodyHandlers.ofString()) .thenAccept(response -> { - assertEquals(response.statusCode(), 404); + assertEquals(404, response.statusCode()); response.headers().firstValue("Content-Type") - .ifPresentOrElse(type -> assertEquals(type, "text/html"), + .ifPresentOrElse(type -> assertEquals("text/html", type), () -> fail("Content-Type not present")); assertTrue(response.body().contains("404 Not Found")); }) @@ -151,8 +153,8 @@ public class OfflineTesting { client.sendAsync(request, BodyHandlers.ofString()) .thenAccept(response -> { System.out.println("response: " + response); - assertEquals(response.statusCode(), 200); - assertEquals(response.body(), "Hello World"); + assertEquals(200, response.statusCode()); + assertEquals("Hello World", response.body()); }) .join(); } @@ -172,8 +174,8 @@ public class OfflineTesting { HttpResponse response = client.send(request, BodyHandlers.ofString()); System.out.println("response: " + response); - assertEquals(response.statusCode(), 200); - assertEquals(response.body(), "Hello chegar!!"); + assertEquals(200, response.statusCode()); + assertEquals("Hello chegar!!", response.body()); } } diff --git a/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java b/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java index c8920771727..361b053fe43 100644 --- a/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java +++ b/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @summary Basic checks for File Processors - * @run testng/othervm FileProcessorPermissionTest + * @run junit/othervm FileProcessorPermissionTest */ import java.nio.file.Path; @@ -32,9 +32,9 @@ import java.nio.file.Paths; import java.util.List; import java.net.http.HttpRequest; import java.net.http.HttpResponse.BodyHandlers; -import org.testng.annotations.Test; import static java.nio.file.StandardOpenOption.*; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.Test; public class FileProcessorPermissionTest { diff --git a/test/jdk/java/net/httpclient/security/filePerms/SecurityBeforeFile.java b/test/jdk/java/net/httpclient/security/filePerms/SecurityBeforeFile.java index d54e27b89ce..c8d7bb64b36 100644 --- a/test/jdk/java/net/httpclient/security/filePerms/SecurityBeforeFile.java +++ b/test/jdk/java/net/httpclient/security/filePerms/SecurityBeforeFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @summary Verifies security checks are performed before existence checks * in pre-defined body processors APIs - * @run testng/othervm SecurityBeforeFile + * @run junit/othervm SecurityBeforeFile */ import java.io.FileNotFoundException; @@ -35,11 +35,13 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse.BodyHandlers; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.nio.file.StandardOpenOption.*; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.fail; public class SecurityBeforeFile { @@ -57,8 +59,7 @@ public class SecurityBeforeFile { } } - @DataProvider(name = "handlerOpenOptions") - public Object[][] handlerOpenOptions() { + public static Object[][] handlerOpenOptions() { return new Object[][] { { new OpenOption[] { } }, { new OpenOption[] { CREATE } }, @@ -66,7 +67,8 @@ public class SecurityBeforeFile { }; } - @Test(dataProvider = "handlerOpenOptions") + @ParameterizedTest + @MethodSource("handlerOpenOptions") public void BodyHandlersOfFileDownload(OpenOption[] openOptions) { Path p = Paths.get("doesNotExistDir"); if (Files.exists(p)) From 2678fe41ca29ca413ab1fbfc69b689c9be1b6c14 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Mon, 2 Mar 2026 14:16:23 +0000 Subject: [PATCH 007/170] 8378870: Remove sun.awt.AWTAccessor from imports in ImageIcon Reviewed-by: serb, kizune, azvegint --- src/java.desktop/share/classes/javax/swing/ImageIcon.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/ImageIcon.java b/src/java.desktop/share/classes/javax/swing/ImageIcon.java index ee6c08ebb15..707a1766eee 100644 --- a/src/java.desktop/share/classes/javax/swing/ImageIcon.java +++ b/src/java.desktop/share/classes/javax/swing/ImageIcon.java @@ -53,8 +53,6 @@ import javax.accessibility.AccessibleRole; import javax.accessibility.AccessibleState; import javax.accessibility.AccessibleStateSet; -import sun.awt.AWTAccessor; - /** * An implementation of the Icon interface that paints Icons * from Images. Images that are created from a URL, filename or byte array From 2adffe0c3cf911df55a79d183d8d63f03b3acc97 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Mon, 2 Mar 2026 14:19:34 +0000 Subject: [PATCH 008/170] 8378872: Mark waitList in FetcherInfo final Reviewed-by: prr, azvegint --- .../share/classes/sun/awt/image/ImageFetcher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java b/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java index 917378389a4..986b79edde9 100644 --- a/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java +++ b/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -314,10 +314,10 @@ class FetcherInfo { static final int MAX_NUM_FETCHERS = 4; static final FetcherInfo FETCHER_INFO = new FetcherInfo(); - Thread[] fetchers; + final Thread[] fetchers; int numFetchers; int numWaiting; - Vector waitList; + final Vector waitList; private FetcherInfo() { fetchers = new Thread[MAX_NUM_FETCHERS]; From cc4ca9fde84c95e369169fe1cd3f62c5d3379d18 Mon Sep 17 00:00:00 2001 From: jonghoonpark Date: Mon, 2 Mar 2026 14:25:41 +0000 Subject: [PATCH 009/170] 8378128: Make PLABStats data members private Reviewed-by: tschatzl, ayang, jwaters --- src/hotspot/share/gc/shared/plab.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shared/plab.hpp b/src/hotspot/share/gc/shared/plab.hpp index 5200f022633..d893a720e2a 100644 --- a/src/hotspot/share/gc/shared/plab.hpp +++ b/src/hotspot/share/gc/shared/plab.hpp @@ -147,14 +147,14 @@ public: // PLAB book-keeping. class PLABStats : public CHeapObj { -protected: - const char* _description; // Identifying string. - Atomic _allocated; // Total allocated Atomic _wasted; // of which wasted (internal fragmentation) Atomic _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size) Atomic _unused; // Unused in last buffer +protected: + const char* _description; // Identifying string. + virtual void reset() { _allocated.store_relaxed(0); _wasted.store_relaxed(0); @@ -164,11 +164,11 @@ protected: public: PLABStats(const char* description) : - _description(description), _allocated(0), _wasted(0), _undo_wasted(0), - _unused(0) + _unused(0), + _description(description) { } virtual ~PLABStats() { } From da99f1a330bfa363507908fe83ac2f8c7cd4b18a Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Mon, 2 Mar 2026 14:29:11 +0000 Subject: [PATCH 010/170] 8378897: assertion failure due to missing depends_only_on_test_impl definition in SqrtHFNode Reviewed-by: qamai --- src/hotspot/share/opto/subnode.hpp | 3 + .../c2/TestDependsOnTestSqrtHFAssertion.java | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/c2/TestDependsOnTestSqrtHFAssertion.java diff --git a/src/hotspot/share/opto/subnode.hpp b/src/hotspot/share/opto/subnode.hpp index a90661c49ee..54cb1d20cd0 100644 --- a/src/hotspot/share/opto/subnode.hpp +++ b/src/hotspot/share/opto/subnode.hpp @@ -564,6 +564,9 @@ public: const Type* bottom_type() const { return Type::HALF_FLOAT; } virtual uint ideal_reg() const { return Op_RegF; } virtual const Type* Value(PhaseGVN* phase) const; + +private: + virtual bool depends_only_on_test_impl() const { return false; } }; diff --git a/test/hotspot/jtreg/compiler/c2/TestDependsOnTestSqrtHFAssertion.java b/test/hotspot/jtreg/compiler/c2/TestDependsOnTestSqrtHFAssertion.java new file mode 100644 index 00000000000..5ad9a927097 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestDependsOnTestSqrtHFAssertion.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8378897 + * @summary assertion failure due to missing depends_only_on_test_impl definition in SqrtHFNode + * @library /test/lib / + * @modules jdk.incubator.vector + * @requires vm.debug & vm.compiler2.enabled + * @run main/othervm --add-modules=jdk.incubator.vector compiler.c2.TestDependsOnTestSqrtHFAssertion + */ + +package compiler.c2; + +import jdk.incubator.vector.*; + +public class TestDependsOnTestSqrtHFAssertion { + public static int x1 = 10; + + public static int x2 = 20; + + public static int y = 30; + + public static int micro(int x1, int x2, int y, int ctr) { + int res = 0; + for (int i = 0; i < ctr; i++) { + if (y != 0) { + if (x1 > 0) { + if (x2 > 0) { + if (y != 0) { + res += (int)Float16.float16ToRawShortBits(Float16.sqrt(Float16.shortBitsToFloat16((short)(x1/y)))); + res += (int)Float16.float16ToRawShortBits(Float16.sqrt(Float16.shortBitsToFloat16((short)(x2/y)))); + } + } + } + } + } + return res; + } + + public static void main(String [] args) { + int res = 0; + for (int i = 0 ; i < 100000; i++) { + res += micro(x1, x2, y, i); + } + IO.println("PASS" + res); + } +} From 7b5b70c9cb67b7e04d92fbf31dc1d1b97ee99613 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Mon, 2 Mar 2026 15:36:54 +0000 Subject: [PATCH 011/170] 8378565: Refactor test/jdk/java/net/httpclient/http3/*.java TestNG tests to JUnit Reviewed-by: vyazici --- .../http3/BadCipherSuiteErrorTest.java | 6 +- .../httpclient/http3/H3BadHeadersTest.java | 59 ++++++------- .../net/httpclient/http3/H3BasicTest.java | 7 +- .../httpclient/http3/H3ConcurrentPush.java | 61 +++++++------- .../http3/H3ConnectionPoolTest.java | 17 ++-- .../http3/H3FixedThreadPoolTest.java | 6 +- .../http3/H3HeaderSizeLimitTest.java | 33 ++++---- .../httpclient/http3/H3HeadersEncoding.java | 27 +++--- .../http3/H3ImplicitPushCancel.java | 51 ++++++------ .../http3/H3InsertionsLimitTest.java | 31 ++++--- .../http3/H3LogHandshakeErrors.java | 32 ++++--- .../http3/H3MemoryHandlingTest.java | 44 +++++----- .../H3MultipleConnectionsToSameHost.java | 23 ++--- .../net/httpclient/http3/H3PushCancel.java | 75 ++++++++--------- .../net/httpclient/http3/H3RedirectTest.java | 9 +- .../net/httpclient/http3/H3ServerPush.java | 83 ++++++++++--------- .../httpclient/http3/H3ServerPushCancel.java | 63 +++++++------- .../http3/H3ServerPushWithDiffTypes.java | 21 ++--- .../net/httpclient/http3/H3SimpleGet.java | 47 ++++++----- .../net/httpclient/http3/H3SimplePost.java | 17 ++-- .../net/httpclient/http3/H3SimpleTest.java | 37 +++++---- .../httpclient/http3/H3StopSendingTest.java | 35 ++++---- .../http3/H3StreamLimitReachedTest.java | 21 ++--- .../net/httpclient/http3/HTTP3NoBodyTest.java | 18 ++-- .../http3/Http3ExpectContinueTest.java | 42 +++++----- .../http3/PeerUniStreamDispatcherTest.java | 46 +++++----- .../net/httpclient/http3/StopSendingTest.java | 27 +++--- .../net/httpclient/http3/StreamLimitTest.java | 57 ++++++------- 28 files changed, 505 insertions(+), 490 deletions(-) diff --git a/test/jdk/java/net/httpclient/http3/BadCipherSuiteErrorTest.java b/test/jdk/java/net/httpclient/http3/BadCipherSuiteErrorTest.java index 727f2c78352..fdfc498b21e 100644 --- a/test/jdk/java/net/httpclient/http3/BadCipherSuiteErrorTest.java +++ b/test/jdk/java/net/httpclient/http3/BadCipherSuiteErrorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 8157105 * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.HttpServerAdapters - * @run testng/othervm/timeout=60 -Djavax.net.debug=ssl -Djdk.httpclient.HttpClient.log=all BadCipherSuiteErrorTest + * @run junit/othervm/timeout=60 -Djavax.net.debug=ssl -Djdk.httpclient.HttpClient.log=all BadCipherSuiteErrorTest * @summary check exception thrown when bad TLS parameters selected */ @@ -49,7 +49,7 @@ import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; /** * When selecting an unacceptable cipher suite the TLS handshake will fail. diff --git a/test/jdk/java/net/httpclient/http3/H3BadHeadersTest.java b/test/jdk/java/net/httpclient/http3/H3BadHeadersTest.java index fb0e1ef3085..fff11f4ceb4 100644 --- a/test/jdk/java/net/httpclient/http3/H3BadHeadersTest.java +++ b/test/jdk/java/net/httpclient/http3/H3BadHeadersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,17 +27,13 @@ * @build jdk.httpclient.test.lib.common.HttpServerAdapters * jdk.test.lib.net.SimpleSSLContext * @compile ../ReferenceTracker.java - * @run testng/othervm -Djdk.internal.httpclient.debug=true H3BadHeadersTest + * @run junit/othervm -Djdk.internal.httpclient.debug=true H3BadHeadersTest * @summary this test verifies the behaviour of the HttpClient when presented * with bad headers */ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.InputStream; @@ -57,10 +53,17 @@ import java.util.concurrent.ExecutionException; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.util.List.of; import static java.util.Map.entry; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.AfterAll; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class H3BadHeadersTest implements HttpServerAdapters { @@ -76,14 +79,13 @@ public class H3BadHeadersTest implements HttpServerAdapters { static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer http3TestServer; // HTTP/3 ( h3 only ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 + h3 ) - String http3URI; - String https2URI; + private static HttpTestServer http3TestServer; // HTTP/3 ( h3 only ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 + h3 ) + private static String http3URI; + private static String https2URI; - @DataProvider(name = "variants") - public Object[][] variants() { + public static Object[][] variants() { return new Object[][] { { http3URI, false}, { https2URI, false}, @@ -93,7 +95,8 @@ public class H3BadHeadersTest implements HttpServerAdapters { } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") void test(String uri, boolean sameClient) throws Exception @@ -126,8 +129,8 @@ public class H3BadHeadersTest implements HttpServerAdapters { .HEAD().setOption(H3_DISCOVERY, config).build(); System.out.println("\nSending HEAD request: " + head); var headResponse = client.send(head, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), Version.HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(Version.HTTP_2, headResponse.version()); } URI uriWithQuery = URI.create(uri + "?BAD_HEADERS=" + i); @@ -163,7 +166,8 @@ public class H3BadHeadersTest implements HttpServerAdapters { System.err.printf("%ntest %s, %s, DONE%n%n", uri, sameClient); } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") void testAsync(String uri, boolean sameClient) throws Exception { @@ -199,8 +203,8 @@ public class H3BadHeadersTest implements HttpServerAdapters { System.out.println("\nSending HEAD request: " + head); var headResponse = client.send(head, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), Version.HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(Version.HTTP_2, headResponse.version()); } URI uriWithQuery = URI.create(uri + "?BAD_HEADERS=" + i); @@ -246,8 +250,7 @@ public class H3BadHeadersTest implements HttpServerAdapters { // sync with implementation. static void assertDetailMessage(Throwable throwable, int iterationIndex) { try { - assertTrue(throwable instanceof IOException, - "Expected IOException, got, " + throwable); + assertInstanceOf(IOException.class, throwable, "Expected IOException, got, " + throwable); assertNotNull(throwable.getMessage(), "No message for " + throwable); assertTrue(throwable.getMessage().contains("malformed response"), "Expected \"malformed response\" in: " + throwable.getMessage()); @@ -269,8 +272,8 @@ public class H3BadHeadersTest implements HttpServerAdapters { } } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { System.out.println("creating servers"); http3TestServer = HttpTestServer.create(Http3DiscoveryMode.HTTP_3_URI_ONLY, sslContext); http3TestServer.addHandler(new BadHeadersHandler(), "/http3/echo"); @@ -285,8 +288,8 @@ public class H3BadHeadersTest implements HttpServerAdapters { System.out.println("server started"); } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { System.err.println("\n\n**** stopping servers\n"); System.out.println("stopping servers"); http3TestServer.stop(); diff --git a/test/jdk/java/net/httpclient/http3/H3BasicTest.java b/test/jdk/java/net/httpclient/http3/H3BasicTest.java index a03df11c1a3..bddb9879ae9 100644 --- a/test/jdk/java/net/httpclient/http3/H3BasicTest.java +++ b/test/jdk/java/net/httpclient/http3/H3BasicTest.java @@ -31,7 +31,7 @@ * jdk.test.lib.Asserts * jdk.test.lib.Utils * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors + * @run junit/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors * -Djdk.internal.httpclient.debug=true * H3BasicTest */ @@ -60,7 +60,6 @@ import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http3.Http3TestServer; import jdk.test.lib.RandomFactory; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; @@ -70,6 +69,8 @@ import static jdk.test.lib.Asserts.assertFileContentsEqual; import static jdk.test.lib.Utils.createTempFile; import static jdk.test.lib.Utils.createTempFileOfSize; +import org.junit.jupiter.api.Test; + public class H3BasicTest implements HttpServerAdapters { private static final Random RANDOM = RandomFactory.getRandom(); @@ -151,7 +152,7 @@ public class H3BasicTest implements HttpServerAdapters { } @Test - public static void test() throws Exception { + public void test() throws Exception { try { initialize(); System.out.println("servers initialized"); diff --git a/test/jdk/java/net/httpclient/http3/H3ConcurrentPush.java b/test/jdk/java/net/httpclient/http3/H3ConcurrentPush.java index 0cdb2f900fd..4392f829258 100644 --- a/test/jdk/java/net/httpclient/http3/H3ConcurrentPush.java +++ b/test/jdk/java/net/httpclient/http3/H3ConcurrentPush.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,responses,trace * -Djdk.httpclient.http3.maxConcurrentPushStreams=45 @@ -73,17 +73,18 @@ import java.util.function.Supplier; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.internal.net.http.common.Utils; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; import static java.net.http.HttpOption.Http3DiscoveryMode.ANY; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class H3ConcurrentPush implements HttpServerAdapters { @@ -92,7 +93,7 @@ public class H3ConcurrentPush implements HttpServerAdapters { static final PrintStream err = System.err; static final PrintStream out = System.out; - static Map PUSH_PROMISES = Map.of( + static final Map PUSH_PROMISES = Map.of( "/x/y/z/1", "the first push promise body", "/x/y/z/2", "the second push promise body", "/x/y/z/3", "the third push promise body", @@ -105,13 +106,13 @@ public class H3ConcurrentPush implements HttpServerAdapters { ); static final String MAIN_RESPONSE_BODY = "the main response body"; - HttpTestServer server; - URI uri; - URI headURI; - ServerPushHandler pushHandler; + private static HttpTestServer server; + private static URI uri; + private static URI headURI; + private static ServerPushHandler pushHandler; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { server = HttpTestServer.create(ANY, SimpleSSLContext.findSSLContext()); pushHandler = new ServerPushHandler(MAIN_RESPONSE_BODY, PUSH_PROMISES); server.addHandler(pushHandler, "/push/"); @@ -122,14 +123,14 @@ public class H3ConcurrentPush implements HttpServerAdapters { headURI = new URI("https://" + server.serverAuthority() + "/head/x"); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { server.stop(); } static HttpResponse assert200ResponseCode(HttpResponse response) { - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); return response; } @@ -137,8 +138,8 @@ public class H3ConcurrentPush implements HttpServerAdapters { HttpRequest headRequest = HttpRequest.newBuilder(headURI) .HEAD().version(Version.HTTP_2).build(); var headResponse = client.send(headRequest, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), Version.HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(Version.HTTP_2, headResponse.version()); } static final class TestPushPromiseHandler implements PushPromiseHandler { @@ -233,16 +234,16 @@ public class H3ConcurrentPush implements HttpServerAdapters { promises.forEach((request, value) -> { HttpResponse response = value.join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); if (PUSH_PROMISES.containsKey(request.uri().getPath())) { - assertEquals(response.body(), PUSH_PROMISES.get(request.uri().getPath())); + assertEquals(PUSH_PROMISES.get(request.uri().getPath()), response.body()); } else { - assertEquals(response.body(), MAIN_RESPONSE_BODY); + assertEquals(MAIN_RESPONSE_BODY, response.body()); } }); int expectedPushes = Math.min(PUSH_PROMISES.size(), maxPushes) + 5; - assertEquals(promises.size(), expectedPushes); + assertEquals(expectedPushes, promises.size()); promises.clear(); @@ -251,12 +252,12 @@ public class H3ConcurrentPush implements HttpServerAdapters { client.sendAsync(HttpRequest.newBuilder(uri).build(), BodyHandlers.ofString()) .thenApply(H3ConcurrentPush::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); } catch (CompletionException c) { throw new AssertionError(c.getCause()); } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // Send with no promise handler, but use pushId bigger than allowed. // This should cause the connection to get closed @@ -268,7 +269,7 @@ public class H3ConcurrentPush implements HttpServerAdapters { client.sendAsync(bigger, BodyHandlers.ofString()) .thenApply(H3ConcurrentPush::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); throw new AssertionError("Expected IOException not thrown"); } catch (CompletionException c) { @@ -287,7 +288,7 @@ public class H3ConcurrentPush implements HttpServerAdapters { throw new AssertionError("Unexpected exception: " + c.getCause(), c.getCause()); } } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // the next time around we should have a new connection, // so we can restart from scratch @@ -298,7 +299,7 @@ public class H3ConcurrentPush implements HttpServerAdapters { var error = errors.stream().findFirst().orElse(null); if (error != null) throw error; var notified = custom.notified; - assertEquals(notified.size(), 9*4*2, "Unexpected notification: " + notified); + assertEquals(9*4*2, notified.size(), "Unexpected notification: " + notified); } } diff --git a/test/jdk/java/net/httpclient/http3/H3ConnectionPoolTest.java b/test/jdk/java/net/httpclient/http3/H3ConnectionPoolTest.java index c90059ccbfd..614d564005b 100644 --- a/test/jdk/java/net/httpclient/http3/H3ConnectionPoolTest.java +++ b/test/jdk/java/net/httpclient/http3/H3ConnectionPoolTest.java @@ -28,7 +28,7 @@ * jdk.test.lib.Asserts * jdk.test.lib.Utils * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors,http3,quic:hs + * @run junit/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors,http3,quic:hs * -Djdk.internal.httpclient.debug=false * H3ConnectionPoolTest */ @@ -53,7 +53,6 @@ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http3.Http3TestServer; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; @@ -65,6 +64,8 @@ import static jdk.test.lib.Asserts.assertEquals; import static jdk.test.lib.Asserts.assertNotEquals; import static jdk.test.lib.Asserts.assertTrue; +import org.junit.jupiter.api.Test; + public class H3ConnectionPoolTest implements HttpServerAdapters { private static final String CLASS_NAME = H3ConnectionPoolTest.class.getSimpleName(); @@ -172,7 +173,7 @@ public class H3ConnectionPoolTest implements HttpServerAdapters { } @Test - public static void testH3Only() throws Exception { + public void testH3Only() throws Exception { System.out.println("\nTesting HTTP/3 only"); initialize(true); try (HttpClient client = getClient()) { @@ -212,12 +213,12 @@ public class H3ConnectionPoolTest implements HttpServerAdapters { } @Test - public static void testH2H3WithTwoAltSVC() throws Exception { + public void testH2H3WithTwoAltSVC() throws Exception { testH2H3(false); } @Test - public static void testH2H3WithAltSVCOnSamePort() throws Exception { + public void testH2H3WithAltSVCOnSamePort() throws Exception { testH2H3(true); } @@ -309,7 +310,7 @@ public class H3ConnectionPoolTest implements HttpServerAdapters { // fourth request with HTTP_3_URI_ONLY should reuse the first connection, // and not reuse the second. HttpRequest request4 = req1Builder.copy().build(); - HttpResponse response4 = client.send(request1, BodyHandlers.ofString()); + HttpResponse response4 = client.send(request4, BodyHandlers.ofString()); assertEquals(HTTP_3, response4.version()); assertEquals(response4.connectionLabel().get(), response1.connectionLabel().get()); assertNotEquals(response4.connectionLabel().get(), response3.connectionLabel().get()); @@ -345,12 +346,12 @@ public class H3ConnectionPoolTest implements HttpServerAdapters { } @Test - public static void testParallelH2H3WithTwoAltSVC() throws Exception { + public void testParallelH2H3WithTwoAltSVC() throws Exception { testH2H3Concurrent(false); } @Test - public static void testParallelH2H3WithAltSVCOnSamePort() throws Exception { + public void testParallelH2H3WithAltSVCOnSamePort() throws Exception { testH2H3Concurrent(true); } diff --git a/test/jdk/java/net/httpclient/http3/H3FixedThreadPoolTest.java b/test/jdk/java/net/httpclient/http3/H3FixedThreadPoolTest.java index 6c181186fda..fd0e8214361 100644 --- a/test/jdk/java/net/httpclient/http3/H3FixedThreadPoolTest.java +++ b/test/jdk/java/net/httpclient/http3/H3FixedThreadPoolTest.java @@ -36,7 +36,7 @@ * JTreg on Tier 7 so that, if the client becomes wedged again, the * JTreg timeout handlers can collect more diagnostic information. * - * @run testng/othervm -Djdk.internal.httpclient.debug=err + * @run junit/othervm -Djdk.internal.httpclient.debug=err * -Djdk.httpclient.HttpClient.log=ssl,headers,requests,responses,errors * -Djdk.httpclient.quic.idleTimeout=666666 * -Djdk.test.server.quic.idleTimeout=666666 @@ -69,7 +69,7 @@ import static java.net.http.HttpOption.H3_DISCOVERY; import static jdk.test.lib.Asserts.assertFileContentsEqual; import static jdk.test.lib.Utils.createTempFileOfSize; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; public class H3FixedThreadPoolTest implements HttpServerAdapters { @@ -118,7 +118,7 @@ public class H3FixedThreadPoolTest implements HttpServerAdapters { } @Test - public static void test() throws Exception { + public void test() throws Exception { try { initialize(); simpleTest(false); diff --git a/test/jdk/java/net/httpclient/http3/H3HeaderSizeLimitTest.java b/test/jdk/java/net/httpclient/http3/H3HeaderSizeLimitTest.java index b48ef9a33f3..d5864989436 100644 --- a/test/jdk/java/net/httpclient/http3/H3HeaderSizeLimitTest.java +++ b/test/jdk/java/net/httpclient/http3/H3HeaderSizeLimitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; -import java.time.Duration; import java.util.concurrent.ExecutionException; import javax.net.ssl.SSLContext; @@ -39,16 +38,16 @@ import jdk.httpclient.test.lib.http3.Http3TestServer; import jdk.httpclient.test.lib.quic.QuicServer; import jdk.internal.net.http.Http3ConnectionAccess; import jdk.internal.net.http.http3.ConnectionSettings; -import jdk.test.lib.Utils; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + /* * @test * @summary Verifies that the HTTP client respects the SETTINGS_MAX_FIELD_SECTION_SIZE setting on HTTP3 connection @@ -57,7 +56,7 @@ import static java.net.http.HttpOption.H3_DISCOVERY; * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters * @build java.net.http/jdk.internal.net.http.Http3ConnectionAccess - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors H3HeaderSizeLimitTest */ @@ -65,11 +64,11 @@ public class H3HeaderSizeLimitTest implements HttpServerAdapters { private static final long HEADER_SIZE_LIMIT_BYTES = 1024; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private HttpTestServer h3Server; - private String requestURIBase; + private static HttpTestServer h3Server; + private static String requestURIBase; - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { final QuicServer quicServer = Http3TestServer.quicServerBuilder() .sslContext(sslContext) .build(); @@ -82,8 +81,8 @@ public class H3HeaderSizeLimitTest implements HttpServerAdapters { .port(h3Server.getAddress().getPort()).build().toString(); } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { if (h3Server != null) { System.out.println("Stopping server " + h3Server.getAddress()); h3Server.stop(); @@ -111,7 +110,7 @@ public class H3HeaderSizeLimitTest implements HttpServerAdapters { final HttpResponse response = client.send( reqBuilder.build(), BodyHandlers.discarding()); - Assert.assertEquals(response.statusCode(), 200, "Unexpected status code"); + Assertions.assertEquals(200, response.statusCode(), "Unexpected status code"); if (i == 3) { var cf = Http3ConnectionAccess.peerSettings(client, response); if (!cf.isDone()) { @@ -131,14 +130,14 @@ public class H3HeaderSizeLimitTest implements HttpServerAdapters { } final HttpRequest request = reqBuilder.build(); System.out.println("Issuing request to " + reqURI); - final IOException thrown = Assert.expectThrows(ProtocolException.class, + final IOException thrown = Assertions.assertThrows(ProtocolException.class, () -> client.send(request, BodyHandlers.discarding())); if (!thrown.getMessage().equals("Request headers size exceeds limit set by peer")) { throw thrown; } // test same with async System.out.println("Issuing async request to " + reqURI); - final ExecutionException asyncThrown = Assert.expectThrows(ExecutionException.class, + final ExecutionException asyncThrown = Assertions.assertThrows(ExecutionException.class, () -> client.sendAsync(request, BodyHandlers.discarding()).get()); if (!(asyncThrown.getCause() instanceof ProtocolException)) { System.err.println("Received unexpected cause"); diff --git a/test/jdk/java/net/httpclient/http3/H3HeadersEncoding.java b/test/jdk/java/net/httpclient/http3/H3HeadersEncoding.java index 44ccfac4a6a..6b7b24f049d 100644 --- a/test/jdk/java/net/httpclient/http3/H3HeadersEncoding.java +++ b/test/jdk/java/net/httpclient/http3/H3HeadersEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @build jdk.httpclient.test.lib.common.HttpServerAdapters * jdk.test.lib.net.SimpleSSLContext * @compile ../ReferenceTracker.java - * @run testng/othervm -Djdk.httpclient.qpack.encoderTableCapacityLimit=4096 + * @run junit/othervm -Djdk.httpclient.qpack.encoderTableCapacityLimit=4096 * -Djdk.httpclient.qpack.decoderMaxTableCapacity=4096 * -Dhttp3.test.server.encoderAllowedHeaders=* * -Dhttp3.test.server.decoderMaxTableCapacity=4096 @@ -40,9 +40,6 @@ import jdk.test.lib.RandomFactory; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -72,17 +69,21 @@ import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; import static jdk.httpclient.test.lib.common.HttpServerAdapters.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + public class H3HeadersEncoding { private static final int REQUESTS_COUNT = 500; private static final int HEADERS_PER_REQUEST = 20; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer http3TestServer; - HeadersHandler serverHeadersHandler; - String http3URI; + private static HttpTestServer http3TestServer; + private static HeadersHandler serverHeadersHandler; + private static String http3URI; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { System.out.println("Creating servers"); http3TestServer = HttpTestServer.create(Http3DiscoveryMode.HTTP_3_URI_ONLY, sslContext); serverHeadersHandler = new HeadersHandler(); @@ -92,8 +93,8 @@ public class H3HeadersEncoding { http3TestServer.start(); } - @AfterTest - public void tearDown() { + @AfterAll + public static void tearDown() { http3TestServer.stop(); } @@ -272,7 +273,7 @@ public class H3HeadersEncoding { } - private class HeadersHandler implements HttpTestHandler { + private static class HeadersHandler implements HttpTestHandler { @Override public void handle(HttpTestExchange t) throws IOException { diff --git a/test/jdk/java/net/httpclient/http3/H3ImplicitPushCancel.java b/test/jdk/java/net/httpclient/http3/H3ImplicitPushCancel.java index 130ccd40cd6..570f84ad620 100644 --- a/test/jdk/java/net/httpclient/http3/H3ImplicitPushCancel.java +++ b/test/jdk/java/net/httpclient/http3/H3ImplicitPushCancel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,responses,trace * H3ImplicitPushCancel @@ -56,17 +56,18 @@ import java.util.concurrent.ConcurrentMap; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.internal.net.http.common.Utils; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.net.http.HttpOption.Http3DiscoveryMode.ANY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class H3ImplicitPushCancel implements HttpServerAdapters { - static Map PUSH_PROMISES = Map.of( + static final Map PUSH_PROMISES = Map.of( "/x/y/z/1", "the first push promise body", "/x/y/z/2", "the second push promise body", "/x/y/z/3", "the third push promise body", @@ -79,12 +80,12 @@ public class H3ImplicitPushCancel implements HttpServerAdapters { ); static final String MAIN_RESPONSE_BODY = "the main response body"; - HttpTestServer server; - URI uri; - URI headURI; + private static HttpTestServer server; + private static URI uri; + private static URI headURI; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { server = HttpTestServer.create(ANY, SimpleSSLContext.findSSLContext()); HttpTestHandler pushHandler = new ServerPushHandler(MAIN_RESPONSE_BODY, PUSH_PROMISES); @@ -96,14 +97,14 @@ public class H3ImplicitPushCancel implements HttpServerAdapters { headURI = new URI("https://" + server.serverAuthority() + "/head/x"); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { server.stop(); } static HttpResponse assert200ResponseCode(HttpResponse response) { - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); return response; } @@ -111,8 +112,8 @@ public class H3ImplicitPushCancel implements HttpServerAdapters { HttpRequest headRequest = HttpRequest.newBuilder(headURI) .HEAD().version(Version.HTTP_2).build(); var headResponse = client.send(headRequest, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), Version.HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(Version.HTTP_2, headResponse.version()); } /* @@ -136,7 +137,7 @@ public class H3ImplicitPushCancel implements HttpServerAdapters { .build(), BodyHandlers.ofString()) .thenApply(H3ImplicitPushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); System.out.println("Got result before error was raised"); throw new AssertionError("should have failed"); @@ -171,14 +172,14 @@ public class H3ImplicitPushCancel implements HttpServerAdapters { promises.putIfAbsent(main.request(), CompletableFuture.completedFuture(main)); promises.forEach((request, value) -> { HttpResponse response = value.join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); if (PUSH_PROMISES.containsKey(request.uri().getPath())) { - assertEquals(response.body(), PUSH_PROMISES.get(request.uri().getPath())); + assertEquals(PUSH_PROMISES.get(request.uri().getPath()), response.body()); } else { - assertEquals(response.body(), MAIN_RESPONSE_BODY); + assertEquals(MAIN_RESPONSE_BODY, response.body()); } }); - assertEquals(promises.size(), PUSH_PROMISES.size() + 1); + assertEquals(PUSH_PROMISES.size() + 1, promises.size()); promises.clear(); @@ -187,13 +188,13 @@ public class H3ImplicitPushCancel implements HttpServerAdapters { client.sendAsync(HttpRequest.newBuilder(uri).build(), BodyHandlers.ofString()) .thenApply(H3ImplicitPushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); } catch (CompletionException c) { throw new AssertionError(c.getCause()); } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); } } diff --git a/test/jdk/java/net/httpclient/http3/H3InsertionsLimitTest.java b/test/jdk/java/net/httpclient/http3/H3InsertionsLimitTest.java index ff38cd4fa98..6eabc23677a 100644 --- a/test/jdk/java/net/httpclient/http3/H3InsertionsLimitTest.java +++ b/test/jdk/java/net/httpclient/http3/H3InsertionsLimitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,13 +27,8 @@ import jdk.httpclient.test.lib.quic.QuicServer; import jdk.internal.net.http.http3.ConnectionSettings; import jdk.internal.net.http.qpack.Encoder; import jdk.internal.net.http.qpack.TableEntry; -import jdk.test.lib.Utils; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -44,12 +39,16 @@ import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpResponse.BodyHandlers; -import java.time.Duration; import java.util.concurrent.CountDownLatch; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + /* * @test * @summary Verifies that the HTTP client respects the maxLiteralWithIndexing @@ -59,7 +58,7 @@ import static java.net.http.HttpOption.H3_DISCOVERY; * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters * @build java.net.http/jdk.internal.net.http.Http3ConnectionAccess - * @run testng/othervm -Djdk.httpclient.qpack.encoderTableCapacityLimit=4096 + * @run junit/othervm -Djdk.httpclient.qpack.encoderTableCapacityLimit=4096 * -Djdk.internal.httpclient.qpack.allowBlockingEncoding=true * -Djdk.httpclient.qpack.decoderMaxTableCapacity=4096 * -Djdk.httpclient.qpack.decoderBlockedStreams=1024 @@ -75,8 +74,8 @@ public class H3InsertionsLimitTest implements HttpServerAdapters { private static final long HEADER_SIZE_LIMIT_BYTES = 8192; private static final long MAX_SERVER_DT_CAPACITY = 4096; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private HttpTestServer h3Server; - private String requestURIBase; + private static HttpTestServer h3Server; + private static String requestURIBase; public static final long MAX_LITERALS_WITH_INDEXING = 32L; private static final CountDownLatch WAIT_FOR_FAILURE = new CountDownLatch(1); @@ -120,8 +119,8 @@ public class H3InsertionsLimitTest implements HttpServerAdapters { exchange.sendResponseHeaders(200, 0); } - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { final QuicServer quicServer = Http3TestServer.quicServerBuilder() .bindAddress(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)) .sslContext(sslContext) @@ -138,8 +137,8 @@ public class H3InsertionsLimitTest implements HttpServerAdapters { .port(h3Server.getAddress().getPort()).build().toString(); } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { if (h3Server != null) { System.out.println("Stopping server " + h3Server.getAddress()); h3Server.stop(); @@ -161,10 +160,10 @@ public class H3InsertionsLimitTest implements HttpServerAdapters { System.out.println("Issuing request to " + reqURI); try { client.send(request, BodyHandlers.discarding()); - Assert.fail("IOException expected"); + Assertions.fail("IOException expected"); } catch (IOException ioe) { System.out.println("Got IOException: " + ioe); - Assert.assertTrue(ioe.getMessage() + Assertions.assertTrue(ioe.getMessage() .contains("Too many literal with indexing")); } finally { WAIT_FOR_FAILURE.countDown(); diff --git a/test/jdk/java/net/httpclient/http3/H3LogHandshakeErrors.java b/test/jdk/java/net/httpclient/http3/H3LogHandshakeErrors.java index f7a258c069c..85a4b6113f0 100644 --- a/test/jdk/java/net/httpclient/http3/H3LogHandshakeErrors.java +++ b/test/jdk/java/net/httpclient/http3/H3LogHandshakeErrors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,8 @@ import java.io.IOException; import java.net.BindException; import java.net.ServerSocket; -import java.net.Socket; import java.net.URI; import java.net.http.HttpClient; -import java.net.http.HttpOption; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; @@ -44,16 +42,16 @@ import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.internal.net.http.quic.QuicConnectionImpl; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; /* * @test @@ -63,7 +61,7 @@ import static org.testng.Assert.*; * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.HttpClient.log=errors * H3LogHandshakeErrors */ @@ -71,14 +69,14 @@ import static org.testng.Assert.*; public class H3LogHandshakeErrors implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private HttpTestServer h3Server; - private ServerSocket tcpServerSocket = null; - private Thread tcpServerThread = null; - private String requestURI; + private static HttpTestServer h3Server; + private static ServerSocket tcpServerSocket = null; + private static Thread tcpServerThread = null; + private static String requestURI; private static Logger clientLogger; - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { // create an H3 only server h3Server = HttpTestServer.create(HTTP_3_URI_ONLY, sslContext); h3Server.addHandler((exchange) -> exchange.sendResponseHeaders(200, 0), "/hello"); @@ -113,8 +111,8 @@ public class H3LogHandshakeErrors implements HttpServerAdapters { } } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { if (h3Server != null) { System.out.println("Stopping server " + h3Server.getAddress()); h3Server.stop(); diff --git a/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java b/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java index c9474be51c2..2fcb7388f7b 100644 --- a/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java +++ b/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,9 +30,6 @@ import jdk.internal.net.http.quic.streams.QuicBidiStream; import jdk.internal.net.quic.QuicVersion; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -52,7 +49,11 @@ import java.util.concurrent.TimeUnit; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; /* * @test @@ -62,7 +63,7 @@ import static org.testng.Assert.*; * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters * @build java.net.http/jdk.internal.net.http.Http3ConnectionAccess - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * -Djdk.httpclient.quic.maxStreamInitialData=16384 @@ -71,11 +72,11 @@ import static org.testng.Assert.*; public class H3MemoryHandlingTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private QuicStandaloneServer server; - private String requestURIBase; + private static QuicStandaloneServer server; + private static String requestURIBase; - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { server = QuicStandaloneServer.newBuilder() .availableVersions(new QuicVersion[]{QuicVersion.QUIC_V1}) .sslContext(sslContext) @@ -87,8 +88,8 @@ public class H3MemoryHandlingTest implements HttpServerAdapters { .port(server.getAddress().getPort()).build().toString(); } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { if (server != null) { System.out.println("Stopping server " + server.getAddress()); server.close(); @@ -125,19 +126,16 @@ public class H3MemoryHandlingTest implements HttpServerAdapters { serverAllWritesDone.complete(false); } }); - HttpClient client = getHttpClient(); - try { + try (HttpClient client = getHttpClient()) { HttpRequest request = getRequest(); final HttpResponse response1 = client.send( request, BodyHandlers.ofInputStream()); - assertEquals(response1.statusCode(), 200); + assertEquals(200, response1.statusCode()); assertFalse(errorCF.isDone(), "Expected the connection to be open"); assertFalse(serverAllWritesDone.isDone()); response1.body().close(); final boolean done = serverAllWritesDone.get(10, TimeUnit.SECONDS); assertFalse(done, "Too much data was buffered by the client"); - } finally { - client.close(); } } @@ -176,12 +174,12 @@ public class H3MemoryHandlingTest implements HttpServerAdapters { handlerCF.completeExceptionally(e); } }); - HttpClient client = getHttpClient(); - try { + + try (HttpClient client = getHttpClient()) { HttpRequest request = getRequest(); final HttpResponse response1 = client.send( - request, BodyHandlers.ofInputStream()); - assertEquals(response1.statusCode(), 200); + request, BodyHandlers.ofInputStream()); + assertEquals(200, response1.statusCode()); assertFalse(errorCF.isDone(), "Expected the connection to be open"); assertFalse(handlerCF.isDone()); assertTrue(writerBlocked.await(10, TimeUnit.SECONDS), @@ -191,10 +189,8 @@ public class H3MemoryHandlingTest implements HttpServerAdapters { try (InputStream body = response1.body()) { receivedResponse = body.readAllBytes(); } - assertEquals(receivedResponse.length, 32768, + assertEquals(32768, receivedResponse.length, "Unexpected response length"); - } finally { - client.close(); } assertTrue(handlerCF.get(10, TimeUnit.SECONDS), "Unexpected result"); diff --git a/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java b/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java index 14149da7815..67ac821b6f7 100644 --- a/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java +++ b/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError * -Djdk.httpclient.quic.minPtoBackoffTime=60 * -Djdk.httpclient.quic.maxPtoBackoffTime=90 * -Djdk.httpclient.quic.maxPtoBackoff=10 @@ -52,7 +52,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError * -Djdk.httpclient.quic.minPtoBackoffTime=45 * -Djdk.httpclient.quic.maxPtoBackoffTime=60 * -Djdk.httpclient.quic.maxPtoBackoff=9 @@ -75,7 +75,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError * -Djdk.httpclient.quic.idleTimeout=120 * -Djdk.httpclient.keepalive.timeout.h3=120 * -Djdk.test.server.quic.idleTimeout=90 @@ -100,7 +100,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError * -Djdk.httpclient.quic.idleTimeout=120 * -Djdk.httpclient.keepalive.timeout.h3=120 * -Djdk.test.server.quic.idleTimeout=90 @@ -161,14 +161,15 @@ import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.internal.net.http.common.Utils; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.Assert; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; import static jdk.internal.net.http.Http3ClientProperties.MAX_STREAM_LIMIT_WAIT_TIMEOUT; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + public class H3MultipleConnectionsToSameHost implements HttpServerAdapters { static HttpTestServer httpsServer; static HttpClient client = null; @@ -223,11 +224,11 @@ public class H3MultipleConnectionsToSameHost implements HttpServerAdapters { } public static void main(String[] args) throws Exception { - test(); + new H3MultipleConnectionsToSameHost().test(); } @Test - public static void test() throws Exception { + public void test() throws Exception { try { long prestart = System.nanoTime(); initialize(); @@ -244,7 +245,7 @@ public class H3MultipleConnectionsToSameHost implements HttpServerAdapters { .GET().build(); long start = System.nanoTime(); var resp = client.send(request, BodyHandlers.ofByteArrayConsumer(b-> {})); - Assert.assertEquals(resp.statusCode(), 200); + Assertions.assertEquals(200, resp.statusCode()); long elapsed = System.nanoTime() - start; System.out.println("First request took: " + elapsed + " nanos (" + TimeUnit.NANOSECONDS.toMillis(elapsed) + " ms)"); final int max = property("simpleget.requests", 50); @@ -298,7 +299,7 @@ public class H3MultipleConnectionsToSameHost implements HttpServerAdapters { } } - list.forEach((cf) -> Assert.assertEquals(cf.join().statusCode(), 200)); + list.forEach((cf) -> Assertions.assertEquals(200, cf.join().statusCode())); client.close(); } catch (Throwable tt) { System.err.println("tt caught"); diff --git a/test/jdk/java/net/httpclient/http3/H3PushCancel.java b/test/jdk/java/net/httpclient/http3/H3PushCancel.java index 324942b67d0..b9e15b7d8e5 100644 --- a/test/jdk/java/net/httpclient/http3/H3PushCancel.java +++ b/test/jdk/java/net/httpclient/http3/H3PushCancel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,responses,trace * -Djdk.httpclient.http3.maxConcurrentPushStreams=5 @@ -69,18 +69,19 @@ import java.util.function.Function; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.internal.net.http.common.Utils; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.net.http.HttpOption.Http3DiscoveryMode.ANY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class H3PushCancel implements HttpServerAdapters { - static Map PUSH_PROMISES = Map.of( + static final Map PUSH_PROMISES = Map.of( "/x/y/z/1", "the first push promise body", "/x/y/z/2", "the second push promise body", "/x/y/z/3", "the third push promise body", @@ -93,13 +94,13 @@ public class H3PushCancel implements HttpServerAdapters { ); static final String MAIN_RESPONSE_BODY = "the main response body"; - HttpTestServer server; - URI uri; - URI headURI; - ServerPushHandler pushHandler; + private static HttpTestServer server; + private static URI uri; + private static URI headURI; + private static ServerPushHandler pushHandler; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { server = HttpTestServer.create(ANY, SimpleSSLContext.findSSLContext()); pushHandler = new ServerPushHandler(MAIN_RESPONSE_BODY, PUSH_PROMISES); server.addHandler(pushHandler, "/push/"); @@ -110,14 +111,14 @@ public class H3PushCancel implements HttpServerAdapters { headURI = new URI("https://" + server.serverAuthority() + "/head/x"); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { server.stop(); } static HttpResponse assert200ResponseCode(HttpResponse response) { - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); return response; } @@ -125,8 +126,8 @@ public class H3PushCancel implements HttpServerAdapters { HttpRequest headRequest = HttpRequest.newBuilder(headURI) .HEAD().version(Version.HTTP_2).build(); var headResponse = client.send(headRequest, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), Version.HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(Version.HTTP_2, headResponse.version()); } @Test @@ -173,14 +174,14 @@ public class H3PushCancel implements HttpServerAdapters { promises.putIfAbsent(main.request(), CompletableFuture.completedFuture(main)); promises.forEach((request, value) -> { HttpResponse response = value.join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); if (PUSH_PROMISES.containsKey(request.uri().getPath())) { - assertEquals(response.body(), PUSH_PROMISES.get(request.uri().getPath())); + assertEquals(PUSH_PROMISES.get(request.uri().getPath()), response.body()); } else { - assertEquals(response.body(), MAIN_RESPONSE_BODY); + assertEquals(MAIN_RESPONSE_BODY, response.body()); } }); - assertEquals(promises.size(), Math.min(PUSH_PROMISES.size(), maxPushes) + 1); + assertEquals(Math.min(PUSH_PROMISES.size(), maxPushes) + 1, promises.size()); promises.clear(); } @@ -190,12 +191,12 @@ public class H3PushCancel implements HttpServerAdapters { client.sendAsync(HttpRequest.newBuilder(uri).build(), BodyHandlers.ofString()) .thenApply(H3PushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); } catch (CompletionException c) { throw new AssertionError(c.getCause()); } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // Send with no promise handler, but use pushId bigger than allowed. // This should cause the connection to get closed @@ -207,7 +208,7 @@ public class H3PushCancel implements HttpServerAdapters { client.sendAsync(bigger, BodyHandlers.ofString()) .thenApply(H3PushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); throw new AssertionError("Expected IOException not thrown"); } catch (CompletionException c) { @@ -226,7 +227,7 @@ public class H3PushCancel implements HttpServerAdapters { throw new AssertionError("Unexpected exception: " + c.getCause(), c.getCause()); } } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // the next time around we should have a new connection // so we can restart from scratch @@ -315,16 +316,16 @@ public class H3PushCancel implements HttpServerAdapters { promises.putIfAbsent(main.request(), CompletableFuture.completedFuture(main)); promises.forEach((request, value) -> { HttpResponse response = value.join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); if (PUSH_PROMISES.containsKey(request.uri().getPath())) { - assertEquals(response.body(), PUSH_PROMISES.get(request.uri().getPath())); + assertEquals(PUSH_PROMISES.get(request.uri().getPath()), response.body()); } else { - assertEquals(response.body(), MAIN_RESPONSE_BODY); + assertEquals(MAIN_RESPONSE_BODY, response.body()); } }); int expectedPushes = Math.min(PUSH_PROMISES.size(), maxPushes) + 1; if (i == 0) expectedPushes--; // pushId == 1 was cancelled - assertEquals(promises.size(), expectedPushes); + assertEquals(expectedPushes, promises.size()); promises.clear(); } @@ -334,12 +335,12 @@ public class H3PushCancel implements HttpServerAdapters { client.sendAsync(HttpRequest.newBuilder(uri).build(), BodyHandlers.ofString()) .thenApply(H3PushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); } catch (CompletionException c) { throw new AssertionError(c.getCause()); } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // Send with no promise handler, but use pushId bigger than allowed. // This should cause the connection to get closed @@ -351,7 +352,7 @@ public class H3PushCancel implements HttpServerAdapters { client.sendAsync(bigger, BodyHandlers.ofString()) .thenApply(H3PushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body ->assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body ->assertEquals(MAIN_RESPONSE_BODY, body)) .join(); throw new AssertionError("Expected IOException not thrown"); } catch (CompletionException c) { @@ -370,7 +371,7 @@ public class H3PushCancel implements HttpServerAdapters { throw new AssertionError("Unexpected exception: " + c.getCause(), c.getCause()); } } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // the next time around we should have a new connection // so we can restart from scratch @@ -379,7 +380,7 @@ public class H3PushCancel implements HttpServerAdapters { errors.forEach(t -> t.printStackTrace(System.out)); var error = errors.stream().findFirst().orElse(null); if (error != null) throw error; - assertEquals(notified.size(), 0, "Unexpected notification: " + notified); + assertEquals(0, notified.size(), "Unexpected notification: " + notified); } } diff --git a/test/jdk/java/net/httpclient/http3/H3RedirectTest.java b/test/jdk/java/net/httpclient/http3/H3RedirectTest.java index 0a5546bc1c1..67a7d99fa71 100644 --- a/test/jdk/java/net/httpclient/http3/H3RedirectTest.java +++ b/test/jdk/java/net/httpclient/http3/H3RedirectTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.common.HttpServerAdapters * @compile ../ReferenceTracker.java - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.HttpClient.log=frames,ssl,requests,responses,errors * -Djdk.internal.httpclient.debug=true * H3RedirectTest @@ -50,11 +50,12 @@ import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.Test; + public class H3RedirectTest implements HttpServerAdapters { static int httpPort; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); @@ -135,7 +136,7 @@ public class H3RedirectTest implements HttpServerAdapters { } @Test - public static void test() throws Exception { + public void test() throws Exception { try { initialize(); simpleTest(); diff --git a/test/jdk/java/net/httpclient/http3/H3ServerPush.java b/test/jdk/java/net/httpclient/http3/H3ServerPush.java index 83f68a15579..50aa817b155 100644 --- a/test/jdk/java/net/httpclient/http3/H3ServerPush.java +++ b/test/jdk/java/net/httpclient/http3/H3ServerPush.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * jdk.httpclient.test.lib.http2.PushHandler * jdk.test.lib.Utils * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm/timeout=960 + * @run junit/othervm/timeout=960 * -Djdk.httpclient.HttpClient.log=errors,requests,headers * -Djdk.internal.httpclient.debug=false * H3ServerPush @@ -66,13 +66,14 @@ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.PushHandler; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.nio.charset.StandardCharsets.UTF_8; import static jdk.test.lib.Utils.createTempFileOfSize; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class H3ServerPush implements HttpServerAdapters { @@ -81,14 +82,14 @@ public class H3ServerPush implements HttpServerAdapters { static final int LOOPS = 13; static final int FILE_SIZE = 512 * 1024 + 343; - static Path tempFile; + private static Path tempFile; - HttpTestServer server; - URI uri; - URI headURI; + private static HttpTestServer server; + private static URI uri; + private static URI headURI; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { tempFile = createTempFileOfSize(CLASS_NAME, ".dat", FILE_SIZE); var sslContext = SimpleSSLContext.findSSLContext(); var h2Server = new Http2TestServer(true, sslContext); @@ -109,12 +110,12 @@ public class H3ServerPush implements HttpServerAdapters { HttpRequest headRequest = HttpRequest.newBuilder(headURI) .HEAD().version(Version.HTTP_2).build(); var headResponse = client.send(headRequest, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), Version.HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(Version.HTTP_2, headResponse.version()); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { server.stop(); } @@ -144,7 +145,7 @@ public class H3ServerPush implements HttpServerAdapters { resultMap.put(request, cf); System.out.println("waiting for response"); var resp = cf.join(); - assertEquals(resp.version(), Version.HTTP_3); + assertEquals(Version.HTTP_3, resp.version()); var seen = new HashSet<>(); resultMap.forEach((k, v) -> { if (seen.add(k)) { @@ -158,16 +159,16 @@ public class H3ServerPush implements HttpServerAdapters { for (HttpRequest r : resultMap.keySet()) { System.out.println("Checking " + r); HttpResponse response = resultMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); - assertEquals(response.body(), tempFileAsString); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); + assertEquals(tempFileAsString, response.body()); } resultMap.forEach((k, v) -> { if (seen.add(k)) { System.out.println("Got " + v.join()); } }); - assertEquals(resultMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultMap.size()); } } @@ -194,11 +195,11 @@ public class H3ServerPush implements HttpServerAdapters { System.err.println("results.size: " + resultMap.size()); for (HttpRequest r : resultMap.keySet()) { HttpResponse response = resultMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); - assertEquals(response.body(), tempFileAsString); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); + assertEquals(tempFileAsString, response.body()); } - assertEquals(resultMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultMap.size()); } } @@ -242,12 +243,12 @@ public class H3ServerPush implements HttpServerAdapters { resultsMap.put(request, cf); for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); String fileAsString = Files.readString(response.body()); - assertEquals(fileAsString, tempFileAsString); + assertEquals(tempFileAsString, fileAsString); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } } @@ -274,12 +275,12 @@ public class H3ServerPush implements HttpServerAdapters { resultsMap.put(request, cf); for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); String fileAsString = Files.readString(response.body()); - assertEquals(fileAsString, tempFileAsString); + assertEquals(tempFileAsString, fileAsString); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } } @@ -340,13 +341,13 @@ public class H3ServerPush implements HttpServerAdapters { resultsMap.put(request, cf); for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes(); String result = new String(ba, UTF_8); - assertEquals(result, tempFileAsString); + assertEquals(tempFileAsString, result); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } } @@ -384,13 +385,13 @@ public class H3ServerPush implements HttpServerAdapters { resultsMap.put(request, cf); for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), Version.HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(Version.HTTP_3, response.version()); byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes(); String result = new String(ba, UTF_8); - assertEquals(result, tempFileAsString); + assertEquals(tempFileAsString, result); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } } } diff --git a/test/jdk/java/net/httpclient/http3/H3ServerPushCancel.java b/test/jdk/java/net/httpclient/http3/H3ServerPushCancel.java index 312b9ac507d..b34e2a1567e 100644 --- a/test/jdk/java/net/httpclient/http3/H3ServerPushCancel.java +++ b/test/jdk/java/net/httpclient/http3/H3ServerPushCancel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,responses,trace * -Djdk.httpclient.http3.maxConcurrentPushStreams=45 @@ -73,9 +73,6 @@ import java.util.function.Supplier; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.internal.net.http.common.Utils; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; @@ -83,10 +80,14 @@ import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; import static java.net.http.HttpOption.Http3DiscoveryMode.ANY; import static java.net.http.HttpOption.H3_DISCOVERY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class H3ServerPushCancel implements HttpServerAdapters { @@ -95,7 +96,7 @@ public class H3ServerPushCancel implements HttpServerAdapters { static final PrintStream err = System.err; static final PrintStream out = System.out; - static Map PUSH_PROMISES = Map.of( + static final Map PUSH_PROMISES = Map.of( "/x/y/z/1", "the first push promise body", "/x/y/z/2", "the second push promise body", "/x/y/z/3", "the third push promise body", @@ -109,13 +110,13 @@ public class H3ServerPushCancel implements HttpServerAdapters { static final String MAIN_RESPONSE_BODY = "the main response body"; static final int REQUESTS = 5; - HttpTestServer server; - URI uri; - URI headURI; - ServerPushHandler pushHandler; + private static HttpTestServer server; + private static URI uri; + private static URI headURI; + private static ServerPushHandler pushHandler; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { server = HttpTestServer.create(ANY, SimpleSSLContext.findSSLContext()); pushHandler = new ServerPushHandler(MAIN_RESPONSE_BODY, PUSH_PROMISES); server.addHandler(pushHandler, "/push/"); @@ -126,14 +127,14 @@ public class H3ServerPushCancel implements HttpServerAdapters { headURI = new URI("https://" + server.serverAuthority() + "/head/x"); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { server.stop(); } static HttpResponse assert200ResponseCode(HttpResponse response) { - assertEquals(response.statusCode(), 200); - assertEquals(response.version(), HTTP_3); + assertEquals(200, response.statusCode()); + assertEquals(HTTP_3, response.version()); return response; } @@ -141,8 +142,8 @@ public class H3ServerPushCancel implements HttpServerAdapters { HttpRequest headRequest = HttpRequest.newBuilder(headURI) .HEAD().version(HTTP_2).build(); var headResponse = client.send(headRequest, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(HTTP_2, headResponse.version()); } static final class TestPushPromiseHandler implements PushPromiseHandler { @@ -283,14 +284,14 @@ public class H3ServerPushCancel implements HttpServerAdapters { throw new AssertionError("Unexpected message: " + msg, ex); } } else { - assertEquals(join(value).body(), PUSH_PROMISES.get(request.uri().getPath())); + assertEquals(PUSH_PROMISES.get(request.uri().getPath()), join(value).body()); } expectedPushIds.add(pushId); - } else assertEquals(pushId.getClass(), Http3PushId.class); + } else assertEquals(Http3PushId.class, pushId.getClass()); } else { HttpResponse response = join(value); - assertEquals(response.statusCode(), 200); - assertEquals(response.body(), MAIN_RESPONSE_BODY); + assertEquals(200, response.statusCode()); + assertEquals(MAIN_RESPONSE_BODY, response.body()); } }); @@ -311,12 +312,12 @@ public class H3ServerPushCancel implements HttpServerAdapters { client.sendAsync(HttpRequest.newBuilder(uri).build(), BodyHandlers.ofString()) .thenApply(H3ServerPushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); } catch (CompletionException c) { throw new AssertionError(c.getCause()); } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // Send with no promise handler, but use pushId bigger than allowed. // This should cause the connection to get closed @@ -328,7 +329,7 @@ public class H3ServerPushCancel implements HttpServerAdapters { client.sendAsync(bigger, BodyHandlers.ofString()) .thenApply(H3ServerPushCancel::assert200ResponseCode) .thenApply(HttpResponse::body) - .thenAccept(body -> assertEquals(body, MAIN_RESPONSE_BODY)) + .thenAccept(body -> assertEquals(MAIN_RESPONSE_BODY, body)) .join(); throw new AssertionError("Expected IOException not thrown"); } catch (CompletionException c) { @@ -347,7 +348,7 @@ public class H3ServerPushCancel implements HttpServerAdapters { throw new AssertionError("Unexpected exception: " + c.getCause(), c.getCause()); } } - assertEquals(promises.size(), 0); + assertEquals(0, promises.size()); // the next time around we should have a new connection, // so we can restart from scratch @@ -408,7 +409,7 @@ public class H3ServerPushCancel implements HttpServerAdapters { // excluding those that got cancelled, // we should have received REQUEST-1 notifications // per push promise and per connection - assertEquals(count, (PUSH_PROMISES.size()-3)*2*(REQUESTS-1), + assertEquals((PUSH_PROMISES.size()-3)*2*(REQUESTS-1), count, "Unexpected notification: " + notified); } } diff --git a/test/jdk/java/net/httpclient/http3/H3ServerPushWithDiffTypes.java b/test/jdk/java/net/httpclient/http3/H3ServerPushWithDiffTypes.java index d00012826ef..a863db43c29 100644 --- a/test/jdk/java/net/httpclient/http3/H3ServerPushWithDiffTypes.java +++ b/test/jdk/java/net/httpclient/http3/H3ServerPushWithDiffTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,responses * H3ServerPushWithDiffTypes @@ -65,11 +65,12 @@ import java.util.function.BiPredicate; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.Test; import static java.net.http.HttpOption.Http3DiscoveryMode.ANY; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; public class H3ServerPushWithDiffTypes implements HttpServerAdapters { @@ -89,8 +90,8 @@ public class H3ServerPushWithDiffTypes implements HttpServerAdapters { HttpRequest headRequest = HttpRequest.newBuilder(headURI) .HEAD().version(Version.HTTP_2).build(); var headResponse = client.send(headRequest, BodyHandlers.ofString()); - assertEquals(headResponse.statusCode(), 200); - assertEquals(headResponse.version(), Version.HTTP_2); + assertEquals(200, headResponse.statusCode()); + assertEquals(Version.HTTP_2, headResponse.version()); } @Test @@ -127,13 +128,13 @@ public class H3ServerPushWithDiffTypes implements HttpServerAdapters { results.put(request, cf); cf.join(); - assertEquals(results.size(), PUSH_PROMISES.size() + 1); + assertEquals(PUSH_PROMISES.size() + 1, results.size()); for (HttpRequest r : results.keySet()) { URI u = r.uri(); var resp = results.get(r).get(); - assertEquals(resp.statusCode(), 200); - assertEquals(resp.version(), Version.HTTP_3); + assertEquals(200, resp.statusCode()); + assertEquals(Version.HTTP_3, resp.version()); BodyAndType body = resp.body(); String result; // convert all body types to String for easier comparison @@ -153,7 +154,7 @@ public class H3ServerPushWithDiffTypes implements HttpServerAdapters { String expected = PUSH_PROMISES.get(r.uri().getPath()); if (expected == null) expected = "the main response body"; - assertEquals(result, expected); + assertEquals(expected, result); } } } diff --git a/test/jdk/java/net/httpclient/http3/H3SimpleGet.java b/test/jdk/java/net/httpclient/http3/H3SimpleGet.java index 3745c32afbf..ae113322cd3 100644 --- a/test/jdk/java/net/httpclient/http3/H3SimpleGet.java +++ b/test/jdk/java/net/httpclient/http3/H3SimpleGet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,14 +30,14 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.httpclient.retryOnStreamlimit=20 * -Djdk.httpclient.redirects.retrylimit=21 * -Dsimpleget.repeat=1 -Dsimpleget.chunks=1 -Dsimpleget.requests=1000 * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Dsimpleget.requests=150 * -Dsimpleget.chunks=16384 * -Djdk.httpclient.retryOnStreamlimit=5 @@ -53,14 +53,14 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.httpclient.retryOnStreamlimit=20 * -Djdk.httpclient.redirects.retrylimit=21 * -Dsimpleget.repeat=1 -Dsimpleget.chunks=1 -Dsimpleget.requests=1000 * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Dsimpleget.requests=150 * -Dsimpleget.chunks=16384 * -Djdk.httpclient.retryOnStreamlimit=5 @@ -77,16 +77,16 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations * -Djdk.httpclient.retryOnStreamlimit=20 * -Djdk.httpclient.redirects.retrylimit=21 * -Dsimpleget.repeat=1 -Dsimpleget.chunks=1 -Dsimpleget.requests=1000 * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations * -Dsimpleget.requests=150 * -Dsimpleget.chunks=16384 @@ -103,16 +103,16 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.internal.httpclient.quic.useNioSelector=true * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.internal.httpclient.quic.useNioSelector=true * -Djdk.httpclient.retryOnStreamlimit=20 * -Djdk.httpclient.redirects.retrylimit=21 * -Dsimpleget.repeat=1 -Dsimpleget.chunks=1 -Dsimpleget.requests=1000 * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.internal.httpclient.quic.useNioSelector=true * -Dsimpleget.requests=150 * -Dsimpleget.chunks=16384 @@ -129,16 +129,16 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.internal.httpclient.quic.useNioSelector=true * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.internal.httpclient.quic.useNioSelector=true * -Djdk.httpclient.retryOnStreamlimit=20 * -Djdk.httpclient.redirects.retrylimit=21 * -Dsimpleget.repeat=1 -Dsimpleget.chunks=1 -Dsimpleget.requests=1000 * H3SimpleGet - * @run testng/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError + * @run junit/othervm/timeout=480 -XX:+HeapDumpOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError * -Djdk.internal.httpclient.quic.useNioSelector=true * -Dsimpleget.requests=150 * -Dsimpleget.chunks=16384 @@ -154,7 +154,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=480 -Djdk.internal.httpclient.quic.congestionController=reno + * @run junit/othervm/timeout=480 -Djdk.internal.httpclient.quic.congestionController=reno * H3SimpleGet * @summary send multiple GET requests using Reno congestion controller */ @@ -198,13 +198,14 @@ import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.Assert; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + public class H3SimpleGet implements HttpServerAdapters { static HttpTestServer httpsServer; static HttpClient client = null; @@ -261,13 +262,13 @@ public class H3SimpleGet implements HttpServerAdapters { } public static void main(String[] args) throws Exception { - test(); + new H3SimpleGet().test(); } static volatile boolean waitBeforeTest = false; @Test - public static void test() throws Exception { + public void test() throws Exception { try { if (waitBeforeTest) { Thread.sleep(20000); @@ -283,7 +284,7 @@ public class H3SimpleGet implements HttpServerAdapters { .GET().build(); long start = System.nanoTime(); var resp = client.send(request, BodyHandlers.ofByteArrayConsumer(b-> {})); - Assert.assertEquals(resp.statusCode(), 200); + Assertions.assertEquals(200, resp.statusCode()); long elapsed = System.nanoTime() - start; System.out.println("Stat: First request took: " + elapsed + " nanos (" + TimeUnit.NANOSECONDS.toMillis(elapsed) + " ms)"); @@ -314,7 +315,7 @@ public class H3SimpleGet implements HttpServerAdapters { + connections.size() + " connections"); } } - list.forEach((cf) -> Assert.assertEquals(cf.join().statusCode(), 200)); + list.forEach((cf) -> Assertions.assertEquals(200, cf.join().statusCode())); } catch (Throwable tt) { System.err.println("tt caught"); tt.printStackTrace(); diff --git a/test/jdk/java/net/httpclient/http3/H3SimplePost.java b/test/jdk/java/net/httpclient/http3/H3SimplePost.java index 4cf46988873..0294f2f69da 100644 --- a/test/jdk/java/net/httpclient/http3/H3SimplePost.java +++ b/test/jdk/java/net/httpclient/http3/H3SimplePost.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=480 H3SimplePost + * @run junit/othervm/timeout=480 H3SimplePost */ // -Djdk.httpclient.HttpClient.log=requests,errors,quic // -Djdk.httpclient.quic.defaultMTU=64000 @@ -37,8 +37,6 @@ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.Assert; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -61,6 +59,9 @@ import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + public class H3SimplePost implements HttpServerAdapters { static HttpTestServer httpsServer; static HttpClient client = null; @@ -115,11 +116,11 @@ public class H3SimplePost implements HttpServerAdapters { } public static void main(String[] args) throws Exception { - test(); + new H3SimplePost().test(); } @Test - public static void test() throws Exception { + public void test() throws Exception { try { long prestart = System.nanoTime(); initialize(); @@ -140,7 +141,7 @@ public class H3SimplePost implements HttpServerAdapters { .build(); long start = System.nanoTime(); var resp = client.send(getRequest, BodyHandlers.ofByteArrayConsumer(b-> {})); - Assert.assertEquals(resp.statusCode(), 200); + Assertions.assertEquals(200, resp.statusCode()); long elapsed = System.nanoTime() - start; System.out.println("First GET request took: " + elapsed + " nanos (" + TimeUnit.NANOSECONDS.toMillis(elapsed) + " ms)"); final int max = 50; @@ -155,7 +156,7 @@ public class H3SimplePost implements HttpServerAdapters { System.out.println("Next " + max + " POST requests took: " + elapsed2 + " nanos (" + TimeUnit.NANOSECONDS.toMillis(elapsed2) + "ms for " + max + " requests): " + elapsed2 / max + " nanos per request (" + TimeUnit.NANOSECONDS.toMillis(elapsed2) / max + " ms)"); - list.forEach((cf) -> Assert.assertEquals(cf.join().statusCode(), 200)); + list.forEach((cf) -> Assertions.assertEquals(200, cf.join().statusCode())); } catch (Throwable tt) { System.err.println("tt caught"); tt.printStackTrace(); diff --git a/test/jdk/java/net/httpclient/http3/H3SimpleTest.java b/test/jdk/java/net/httpclient/http3/H3SimpleTest.java index 1880d436501..4258f3bac73 100644 --- a/test/jdk/java/net/httpclient/http3/H3SimpleTest.java +++ b/test/jdk/java/net/httpclient/http3/H3SimpleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,16 +32,17 @@ import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + /* * @test * @summary Basic test to verify that simple GET/POST/HEAD @@ -50,21 +51,21 @@ import static java.net.http.HttpOption.H3_DISCOVERY; * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * H3SimpleTest - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * -Djava.net.preferIPv6Addresses=true * H3SimpleTest - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * -Djava.net.preferIPv4Stack=true * H3SimpleTest - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * -Djdk.internal.httpclient.quic.congestionController=reno @@ -74,11 +75,11 @@ import static java.net.http.HttpOption.H3_DISCOVERY; public class H3SimpleTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private HttpTestServer h3Server; - private String requestURI; + private static HttpTestServer h3Server; + private static String requestURI; - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { // create an H3 only server h3Server = HttpTestServer.create(HTTP_3_URI_ONLY, sslContext); h3Server.addHandler((exchange) -> exchange.sendResponseHeaders(200, 0), "/hello"); @@ -87,8 +88,8 @@ public class H3SimpleTest implements HttpServerAdapters { requestURI = "https://" + h3Server.serverAuthority() + "/hello"; } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { if (h3Server != null) { System.out.println("Stopping server " + h3Server.getAddress()); h3Server.stop(); @@ -113,18 +114,18 @@ public class H3SimpleTest implements HttpServerAdapters { final HttpRequest req1 = reqBuilder.copy().GET().build(); System.out.println("Issuing request: " + req1); final HttpResponse resp1 = client.send(req1, BodyHandlers.discarding()); - Assert.assertEquals(resp1.statusCode(), 200, "unexpected response code for GET request"); + Assertions.assertEquals(200, resp1.statusCode(), "unexpected response code for GET request"); // POST final HttpRequest req2 = reqBuilder.copy().POST(BodyPublishers.ofString("foo")).build(); System.out.println("Issuing request: " + req2); final HttpResponse resp2 = client.send(req2, BodyHandlers.discarding()); - Assert.assertEquals(resp2.statusCode(), 200, "unexpected response code for POST request"); + Assertions.assertEquals(200, resp2.statusCode(), "unexpected response code for POST request"); // HEAD final HttpRequest req3 = reqBuilder.copy().HEAD().build(); System.out.println("Issuing request: " + req3); final HttpResponse resp3 = client.send(req3, BodyHandlers.discarding()); - Assert.assertEquals(resp3.statusCode(), 200, "unexpected response code for HEAD request"); + Assertions.assertEquals(200, resp3.statusCode(), "unexpected response code for HEAD request"); } } diff --git a/test/jdk/java/net/httpclient/http3/H3StopSendingTest.java b/test/jdk/java/net/httpclient/http3/H3StopSendingTest.java index 5b017c15d9b..86b12a1dae6 100644 --- a/test/jdk/java/net/httpclient/http3/H3StopSendingTest.java +++ b/test/jdk/java/net/httpclient/http3/H3StopSendingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @summary Verifies that the client reacts correctly to the receipt of a STOP_SENDING frame. * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.common.HttpServerAdapters - * @run testng/othervm/timeout=40 -Djdk.internal.httpclient.debug=true -Djdk.httpclient.HttpClient.log=trace,errors,headers + * @run junit/othervm/timeout=40 -Djdk.internal.httpclient.debug=true -Djdk.httpclient.HttpClient.log=trace,errors,headers * H3StopSendingTest */ @@ -35,9 +35,6 @@ import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler; import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; import jdk.test.lib.net.SimpleSSLContext; import jdk.internal.net.http.http3.Http3Error; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -53,14 +50,18 @@ import java.util.concurrent.ExecutionException; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class H3StopSendingTest { - HttpTestServer h3TestServer; - HttpRequest postRequestNoError, postRequestError; - HttpRequest postRequestNoErrorWithData, postRequestErrorWithData; - URI h3TestServerUriNoError, h3TestServerUriError; + private static HttpTestServer h3TestServer; + private static HttpRequest postRequestNoError, postRequestError; + private static HttpRequest postRequestNoErrorWithData, postRequestErrorWithData; + private static URI h3TestServerUriNoError, h3TestServerUriError; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); static final String TEST_ROOT_PATH = "/h3_stop_sending_test"; @@ -81,13 +82,13 @@ public class H3StopSendingTest { err.println(resp.headers()); err.println(resp.body()); err.println(resp.statusCode()); - assertEquals(resp.statusCode(), 200); + assertEquals(200, resp.statusCode()); resp = client.sendAsync(postRequestNoErrorWithData, HttpResponse.BodyHandlers.ofString()).get(); err.println(resp.headers()); err.println(resp.body()); err.println(resp.statusCode()); - assertEquals(resp.statusCode(), 200); - assertEquals(resp.body(), RESPONSE_MESSAGE.repeat(MESSAGE_REPEAT)); + assertEquals(200, resp.statusCode()); + assertEquals(RESPONSE_MESSAGE.repeat(MESSAGE_REPEAT), resp.body()); } } @@ -125,8 +126,8 @@ public class H3StopSendingTest { } } - @BeforeTest - public void setup() throws IOException { + @BeforeAll + public static void setup() throws IOException { h3TestServer = HttpTestServer.create(HTTP_3_URI_ONLY, sslContext); h3TestServer.addHandler(new ServerRequestStopSendingHandler(), TEST_ROOT_PATH); @@ -162,8 +163,8 @@ public class H3StopSendingTest { .build(); } - @AfterTest - public void afterTest() { + @AfterAll + public static void afterTest() { h3TestServer.stop(); } diff --git a/test/jdk/java/net/httpclient/http3/H3StreamLimitReachedTest.java b/test/jdk/java/net/httpclient/http3/H3StreamLimitReachedTest.java index a4524b9ae5e..1ac4a750d77 100644 --- a/test/jdk/java/net/httpclient/http3/H3StreamLimitReachedTest.java +++ b/test/jdk/java/net/httpclient/http3/H3StreamLimitReachedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * jdk.test.lib.Asserts * jdk.test.lib.Utils * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors,http3,quic:control + * @run junit/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors,http3,quic:control * -Djdk.internal.httpclient.debug=false * -Djdk.internal.httpclient.quic.maxBidiStreams=1 * H3StreamLimitReachedTest @@ -77,7 +77,7 @@ * jdk.test.lib.Asserts * jdk.test.lib.Utils * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors,http3,quic:control + * @run junit/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors,http3,quic:control * -Djdk.internal.httpclient.debug=false * -Djdk.internal.httpclient.quic.maxBidiStreams=1 * -Djdk.httpclient.http3.maxStreamLimitTimeout=0 @@ -114,7 +114,6 @@ import jdk.httpclient.test.lib.http2.Http2TestExchange; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http3.Http3TestServer; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; @@ -125,7 +124,9 @@ import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static jdk.test.lib.Asserts.assertEquals; import static jdk.test.lib.Asserts.assertNotEquals; import static jdk.test.lib.Asserts.assertTrue; -import static org.testng.Assert.assertFalse; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import org.junit.jupiter.api.Test; public class H3StreamLimitReachedTest implements HttpServerAdapters { @@ -329,7 +330,7 @@ public class H3StreamLimitReachedTest implements HttpServerAdapters { } @Test - public static void testH3Only() throws Exception { + public void testH3Only() throws Exception { System.out.println("\nTesting HTTP/3 only"); initialize(true); try (HttpClient client = getClient()) { @@ -402,12 +403,12 @@ public class H3StreamLimitReachedTest implements HttpServerAdapters { } @Test - public static void testH2H3WithTwoAltSVC() throws Exception { + public void testH2H3WithTwoAltSVC() throws Exception { testH2H3(false); } @Test - public static void testH2H3WithAltSVCOnSamePort() throws Exception { + public void testH2H3WithAltSVCOnSamePort() throws Exception { testH2H3(true); } @@ -627,12 +628,12 @@ public class H3StreamLimitReachedTest implements HttpServerAdapters { } @Test - public static void testParallelH2H3WithTwoAltSVC() throws Exception { + public void testParallelH2H3WithTwoAltSVC() throws Exception { testH2H3Concurrent(false); } @Test - public static void testParallelH2H3WithAltSVCOnSamePort() throws Exception { + public void testParallelH2H3WithAltSVCOnSamePort() throws Exception { testH2H3Concurrent(true); } diff --git a/test/jdk/java/net/httpclient/http3/HTTP3NoBodyTest.java b/test/jdk/java/net/httpclient/http3/HTTP3NoBodyTest.java index 601e40c7dc6..b43ce8dcf79 100644 --- a/test/jdk/java/net/httpclient/http3/HTTP3NoBodyTest.java +++ b/test/jdk/java/net/httpclient/http3/HTTP3NoBodyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * jdk.httpclient.test.lib.http3.Http3TestServer * jdk.httpclient.test.lib.common.HttpServerAdapters * @compile ../ReferenceTracker.java - * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors + * @run junit/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors * -Djdk.internal.httpclient.debug=true * HTTP3NoBodyTest * @summary this is a copy of http2/NoBodyTest over HTTP/3 @@ -38,8 +38,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.*; -import javax.net.ssl.*; +import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpHeaders; import java.net.http.HttpRequest; @@ -48,9 +47,12 @@ import java.net.http.HttpOption.Http3DiscoveryMode; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.util.Random; -import java.util.concurrent.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; +import javax.net.ssl.SSLContext; + import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.Http2TestExchange; @@ -58,7 +60,6 @@ import jdk.httpclient.test.lib.http2.Http2Handler; import jdk.httpclient.test.lib.http3.Http3TestServer; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.RandomFactory; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.ALT_SVC; @@ -66,7 +67,8 @@ import static java.net.http.HttpOption.Http3DiscoveryMode.ANY; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -@Test +import org.junit.jupiter.api.Test; + public class HTTP3NoBodyTest { private static final Random RANDOM = RandomFactory.getRandom(); @@ -119,7 +121,7 @@ public class HTTP3NoBodyTest { } @Test - public static void runtest() throws Exception { + public void runtest() throws Exception { try { initialize(); warmup(false); diff --git a/test/jdk/java/net/httpclient/http3/Http3ExpectContinueTest.java b/test/jdk/java/net/httpclient/http3/Http3ExpectContinueTest.java index 53ce6a68d38..1cf6900ed5d 100644 --- a/test/jdk/java/net/httpclient/http3/Http3ExpectContinueTest.java +++ b/test/jdk/java/net/httpclient/http3/Http3ExpectContinueTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @compile ../ReferenceTracker.java * @build jdk.httpclient.test.lib.common.HttpServerAdapters - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,headers * Http3ExpectContinueTest */ @@ -36,11 +36,6 @@ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http3.Http3TestServer; import jdk.httpclient.test.lib.quic.QuicServer; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.TestException; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -60,15 +55,20 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import static java.net.http.HttpClient.Version.HTTP_3; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class Http3ExpectContinueTest implements HttpServerAdapters { - ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + private static final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; - Http3TestServer http3TestServer; + private static Http3TestServer http3TestServer; - URI h3postUri, h3forcePostUri, h3hangUri; + private static URI h3postUri, h3forcePostUri, h3hangUri; static PrintStream err = new PrintStream(System.err); static PrintStream out = new PrintStream(System.out); @@ -78,8 +78,7 @@ public class Http3ExpectContinueTest implements HttpServerAdapters { static final String BODY = "Post body"; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - @DataProvider(name = "uris") - public Object[][] urisData() { + public static Object[][] urisData() { return new Object[][]{ // URI, Expected Status Code, Will finish with Exception { h3postUri, 200, false }, @@ -88,7 +87,8 @@ public class Http3ExpectContinueTest implements HttpServerAdapters { }; } - @Test(dataProvider = "uris") + @ParameterizedTest + @MethodSource("urisData") public void test(URI uri, int expectedStatusCode, boolean exceptionally) throws CancellationException, InterruptedException, ExecutionException, IOException { @@ -149,8 +149,8 @@ public class Http3ExpectContinueTest implements HttpServerAdapters { } } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { final QuicServer quicServer = Http3TestServer.quicServerBuilder() .sslContext(sslContext) .build(); @@ -167,8 +167,8 @@ public class Http3ExpectContinueTest implements HttpServerAdapters { http3TestServer.start(); } - @AfterTest - public void teardown() throws IOException { + @AfterAll + public static void teardown() throws IOException { var error = TRACKER.check(500); if (error != null) throw error; http3TestServer.stop(); @@ -233,11 +233,11 @@ public class Http3ExpectContinueTest implements HttpServerAdapters { } if (exceptionally && testThrowable != null) { err.println("Finished exceptionally Test throwable: " + testThrowable); - assertEquals(IOException.class, testThrowable.getClass()); + assertEquals(testThrowable.getClass(), IOException.class); } else if (exceptionally) { - throw new TestException("Expected case to finish with an IOException but testException is null"); + fail("Expected case to finish with an IOException but testException is null"); } else if (resp != null) { - assertEquals(resp.statusCode(), expectedStatusCode); + assertEquals(expectedStatusCode, resp.statusCode()); err.println("Request completed successfully for path " + path); err.println("Response Headers: " + resp.headers()); err.println("Response Status Code: " + resp.statusCode()); diff --git a/test/jdk/java/net/httpclient/http3/PeerUniStreamDispatcherTest.java b/test/jdk/java/net/httpclient/http3/PeerUniStreamDispatcherTest.java index be1b8304bf1..fc6d43bb472 100644 --- a/test/jdk/java/net/httpclient/http3/PeerUniStreamDispatcherTest.java +++ b/test/jdk/java/net/httpclient/http3/PeerUniStreamDispatcherTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=out * PeerUniStreamDispatcherTest * @summary Unit test for the PeerUniStreamDispatcher @@ -45,8 +45,8 @@ import jdk.internal.net.http.quic.streams.QuicReceiverStream; import jdk.internal.net.http.quic.streams.QuicStreamReader; import jdk.internal.net.http.quic.streams.QuicStreams; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; public class PeerUniStreamDispatcherTest { @@ -301,7 +301,7 @@ public class PeerUniStreamDispatcherTest { assertTrue(reader.connected()); int size = VariableLengthEncoder.getEncodedSize(code); ByteBuffer buffer = ByteBuffer.allocate(size); - assertEquals(buffer.remaining(), size); + assertEquals(size, buffer.remaining()); VariableLengthEncoder.encode(buffer, code); buffer.flip(); stream.buffers.add(buffer); @@ -313,7 +313,7 @@ public class PeerUniStreamDispatcherTest { // will loop correctly. size = VariableLengthEncoder.getEncodedSize(1L << 62 - 5); ByteBuffer buffer2 = ByteBuffer.allocate(size); - assertEquals(buffer2.remaining(), size); + assertEquals(size, buffer2.remaining()); VariableLengthEncoder.encode(buffer2, 1L << 62 - 5); buffer2.flip(); stream.buffers.add(ByteBuffer.wrap(new byte[] {buffer2.get()})); @@ -328,7 +328,7 @@ public class PeerUniStreamDispatcherTest { assertFalse(reader.connected()); assertFalse(dispatcher.dispatched.isEmpty()); assertTrue(stream.buffers.isEmpty()); - assertEquals(dispatcher.dispatched.size(), 1); + assertEquals(1, dispatcher.dispatched.size()); var dispatched = dispatcher.dispatched.get(0); checkDispatched(type, code, stream, dispatched); } @@ -343,30 +343,30 @@ public class PeerUniStreamDispatcherTest { case RESERVED -> DispatchedStream.ReservedStream.class; case UNKNOWN -> DispatchedStream.UnknownStream.class; }; - assertEquals(dispatched.getClass(), streamClass, + assertEquals(streamClass, dispatched.getClass(), "unexpected dispatched class " + dispatched + " for " + type); if (dispatched instanceof DispatchedStream.StandardStream st) { System.out.println("Got expected stream: " + st); - assertEquals(st.type(), type); - assertEquals(st.stream, stream); + assertEquals(type, st.type()); + assertEquals(stream, st.stream); } else if (dispatched instanceof DispatchedStream.ReservedStream res) { System.out.println("Got expected stream: " + res); - assertEquals(res.type(), type); - assertEquals(res.stream, stream); - assertEquals(res.code(), code); + assertEquals(type, res.type()); + assertEquals(stream, res.stream); + assertEquals(code, res.code()); assertTrue(Http3Streams.isReserved(res.code())); } else if (dispatched instanceof DispatchedStream.UnknownStream unk) { System.out.println("Got expected stream: " + unk); - assertEquals(unk.type(), type); - assertEquals(unk.stream, stream); - assertEquals(unk.code(), code); + assertEquals(type, unk.type()); + assertEquals(stream, unk.stream); + assertEquals(code, unk.code()); assertFalse(Http3Streams.isReserved(unk.code())); } else if (dispatched instanceof DispatchedStream.PushStream push) { System.out.println("Got expected stream: " + push); - assertEquals(push.type(), type); - assertEquals(push.stream, stream); - assertEquals(push.pushId, 1L << 62 - 5); - assertEquals(push.type(), DISPATCHED_STREAM.PUSH); + assertEquals(type, push.type()); + assertEquals(stream, push.stream); + assertEquals(1L << 62 - 5, push.pushId); + assertEquals(DISPATCHED_STREAM.PUSH, push.type()); } } @@ -406,9 +406,9 @@ public class PeerUniStreamDispatcherTest { SequentialScheduler scheduler = stream.scheduler; assertTrue(reader.connected()); int size = VariableLengthEncoder.getEncodedSize(code); - assertEquals(size, 8); + assertEquals(8, size); ByteBuffer buffer = ByteBuffer.allocate(size); - assertEquals(buffer.remaining(), size); + assertEquals(size, buffer.remaining()); VariableLengthEncoder.encode(buffer, code); buffer.flip(); dispatcher.start(); @@ -428,7 +428,7 @@ public class PeerUniStreamDispatcherTest { assertFalse(reader.connected()); assertFalse(dispatcher.dispatched.isEmpty()); assertTrue(stream.buffers.isEmpty()); - assertEquals(dispatcher.dispatched.size(), 1); + assertEquals(1, dispatcher.dispatched.size()); var dispatched = dispatcher.dispatched.get(0); checkDispatched(type, code, stream, dispatched); } diff --git a/test/jdk/java/net/httpclient/http3/StopSendingTest.java b/test/jdk/java/net/httpclient/http3/StopSendingTest.java index ff1b8db7bc8..8c9a6f84b65 100644 --- a/test/jdk/java/net/httpclient/http3/StopSendingTest.java +++ b/test/jdk/java/net/httpclient/http3/StopSendingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,14 +44,15 @@ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.internal.net.http.ResponseSubscribers; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + /* * @test * @summary Exercises the HTTP3 client to send a STOP_SENDING frame @@ -59,17 +60,17 @@ import static java.net.http.HttpOption.H3_DISCOVERY; * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters * @compile ../ReferenceTracker.java - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors StopSendingTest */ public class StopSendingTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private HttpTestServer h3Server; - private String requestURIBase; + private static HttpTestServer h3Server; + private static String requestURIBase; - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { h3Server = HttpTestServer.create(HTTP_3_URI_ONLY, sslContext); h3Server.addHandler(new Handler(), "/hello"); h3Server.start(); @@ -79,8 +80,8 @@ public class StopSendingTest implements HttpServerAdapters { } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { if (h3Server != null) { System.out.println("Stopping server " + h3Server.getAddress()); h3Server.stop(); @@ -154,7 +155,7 @@ public class StopSendingTest implements HttpServerAdapters { // of the Future instance, sometimes the Future.cancel(true) results // in an ExecutionException which wraps the CancellationException. // TODO: fix the actual race condition and then expect only CancellationException here - final Exception actualException = Assert.expectThrows(Exception.class, futureResp::get); + final Exception actualException = Assertions.assertThrows(Exception.class, futureResp::get); if (actualException instanceof CancellationException) { // expected System.out.println("Received the expected CancellationException"); diff --git a/test/jdk/java/net/httpclient/http3/StreamLimitTest.java b/test/jdk/java/net/httpclient/http3/StreamLimitTest.java index e0610cf89b8..9e15db9ceb9 100644 --- a/test/jdk/java/net/httpclient/http3/StreamLimitTest.java +++ b/test/jdk/java/net/httpclient/http3/StreamLimitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,14 +45,15 @@ import jdk.httpclient.test.lib.quic.QuicServerConnection; import jdk.internal.net.http.quic.QuicTransportParameters; import jdk.internal.net.http.quic.QuicTransportParameters.ParameterId; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.H3_DISCOVERY; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + /* * @test * @summary verifies that when the Quic stream limit is reached @@ -64,17 +65,17 @@ import static java.net.http.HttpOption.H3_DISCOVERY; * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters * jdk.httpclient.test.lib.http3.Http3TestServer - * @run testng/othervm -Djdk.internal.httpclient.debug=true StreamLimitTest + * @run junit/othervm -Djdk.internal.httpclient.debug=true StreamLimitTest */ public class StreamLimitTest { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private HttpTestServer server; - private QuicServer quicServer; - private URI requestURI; - private volatile QuicServerConnection latestServerConn; + private static HttpTestServer server; + private static QuicServer quicServer; + private static URI requestURI; + private static volatile QuicServerConnection latestServerConn; - private final class Handler implements HttpTestHandler { + private static final class Handler implements HttpTestHandler { @Override public void handle(HttpTestExchange exchange) throws IOException { @@ -97,8 +98,8 @@ public class StreamLimitTest { } } - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { quicServer = Http3TestServer.quicServerBuilder().sslContext(sslContext).build(); final Http3TestServer h3Server = new Http3TestServer(quicServer) { @Override @@ -118,8 +119,8 @@ public class StreamLimitTest { requestURI = new URI("https://" + server.serverAuthority() + "/foo"); } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { latestServerConn = null; if (server != null) { server.stop(); @@ -161,8 +162,8 @@ public class StreamLimitTest { System.out.println("Sending request " + i + " to " + requestURI); final HttpResponse resp = client.send(req, HttpResponse.BodyHandlers.ofString()); - Assert.assertEquals(resp.version(), HTTP_3, "Unexpected response version"); - Assert.assertEquals(resp.statusCode(), 200, "Unexpected response code"); + Assertions.assertEquals(HTTP_3, resp.version(), "Unexpected response version"); + Assertions.assertEquals(200, resp.statusCode(), "Unexpected response code"); final String respBody = resp.body(); System.out.println("Request " + i + " was handled by server connection: " + respBody); if (i == 1) { @@ -170,7 +171,7 @@ public class StreamLimitTest { // to this request requestHandledBy = respBody; } else { - Assert.assertEquals(respBody, requestHandledBy, "Request was handled by an" + + Assertions.assertEquals(requestHandledBy, respBody, "Request was handled by an" + " unexpected server connection"); } } @@ -193,20 +194,20 @@ public class StreamLimitTest { + requestURI); final HttpResponse resp = client.send(reqWithTimeout, HttpResponse.BodyHandlers.ofString()); - Assert.assertEquals(resp.version(), HTTP_3, "Unexpected response version"); - Assert.assertEquals(resp.statusCode(), 200, "Unexpected response code"); + Assertions.assertEquals(HTTP_3, resp.version(), "Unexpected response version"); + Assertions.assertEquals(200, resp.statusCode(), "Unexpected response code"); final String respBody = resp.body(); System.out.println("Request " + i + " was handled by server connection: " + respBody); if (i == 1) { // first request after the limit was hit. // verify that it was handled by a new connection and not the one that handled // the previous N requests - Assert.assertNotEquals(respBody, requestHandledBy, "Request was expected to be" + + Assertions.assertNotEquals(requestHandledBy, respBody, "Request was expected to be" + " handled by a new server connection, but wasn't"); // keep track this new server connection id which responded to this request requestHandledBy = respBody; } else { - Assert.assertEquals(respBody, requestHandledBy, "Request was handled by an" + + Assertions.assertEquals(requestHandledBy, respBody, "Request was handled by an" + " unexpected server connection"); } } @@ -231,13 +232,13 @@ public class StreamLimitTest { " to " + requestURI); final HttpResponse resp = client.send(reqWithTimeout, HttpResponse.BodyHandlers.ofString()); - Assert.assertEquals(resp.version(), HTTP_3, "Unexpected response version"); - Assert.assertEquals(resp.statusCode(), 200, "Unexpected response code"); + Assertions.assertEquals(HTTP_3, resp.version(), "Unexpected response version"); + Assertions.assertEquals(200, resp.statusCode(), "Unexpected response code"); final String respBody = resp.body(); System.out.println("Request " + i + " was handled by server connection: " + respBody); // all these requests should be handled by the same server connection which handled // the previous requests - Assert.assertEquals(respBody, requestHandledBy, "Request was handled by an" + + Assertions.assertEquals(requestHandledBy, respBody, "Request was handled by an" + " unexpected server connection"); } // at this point the newer limit for bidi stream creation has reached on the client. @@ -254,12 +255,12 @@ public class StreamLimitTest { System.out.println("Sending request, without timeout, to " + requestURI); final HttpResponse finalResp = client.send(finalReq, HttpResponse.BodyHandlers.ofString()); - Assert.assertEquals(finalResp.version(), HTTP_3, "Unexpected response version"); - Assert.assertEquals(finalResp.statusCode(), 200, "Unexpected response code"); + Assertions.assertEquals(HTTP_3, finalResp.version(), "Unexpected response version"); + Assertions.assertEquals(200, finalResp.statusCode(), "Unexpected response code"); final String finalRespBody = finalResp.body(); System.out.println("Request was handled by server connection: " + finalRespBody); // this request should have been handled by a new server connection - Assert.assertNotEquals(finalRespBody, requestHandledBy, "Request was handled by an" + + Assertions.assertNotEquals(requestHandledBy, finalRespBody, "Request was handled by an" + " unexpected server connection"); } } From 4fbc29199c207e426176749f51dfc6994dede044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Arias=20de=20Reyna=20Dom=C3=ADnguez?= Date: Mon, 2 Mar 2026 16:16:31 +0000 Subject: [PATCH 012/170] 8377777: Improve logging when rejecting assets from the AOT archive Reviewed-by: adinn, iklam, stuefe --- src/hotspot/share/oops/constantPool.cpp | 3 +- src/hotspot/share/oops/cpCache.cpp | 56 +++++++++++++------ src/hotspot/share/oops/cpCache.hpp | 2 +- .../AOTLinkedVarHandles.java | 1 + 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 640b2f2460f..456333efad0 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -310,8 +310,9 @@ void ConstantPool::iterate_archivable_resolved_references(Function function) { if (method_entries != nullptr) { for (int i = 0; i < method_entries->length(); i++) { ResolvedMethodEntry* rme = method_entries->adr_at(i); + const char* rejection_reason = nullptr; if (rme->is_resolved(Bytecodes::_invokehandle) && rme->has_appendix() && - cache()->can_archive_resolved_method(this, rme)) { + cache()->can_archive_resolved_method(this, rme, rejection_reason)) { int rr_index = rme->resolved_references_index(); assert(resolved_reference_at(rr_index) != nullptr, "must exist"); function(rr_index); diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index 75cdcb5310a..34d7aa10299 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -450,12 +450,15 @@ void ConstantPoolCache::remove_resolved_field_entries_if_non_deterministic() { Symbol* klass_name = cp->klass_name_at(klass_cp_index); Symbol* name = cp->uncached_name_ref_at(cp_index); Symbol* signature = cp->uncached_signature_ref_at(cp_index); - log.print("%s field CP entry [%3d]: %s => %s.%s:%s%s", - (archived ? "archived" : "reverted"), - cp_index, - cp->pool_holder()->name()->as_C_string(), - klass_name->as_C_string(), name->as_C_string(), signature->as_C_string(), - rfi->is_resolved(Bytecodes::_getstatic) || rfi->is_resolved(Bytecodes::_putstatic) ? " *** static" : ""); + if (resolved) { + log.print("%s field CP entry [%3d]: %s => %s.%s:%s%s%s", + (archived ? "archived" : "reverted"), + cp_index, + cp->pool_holder()->name()->as_C_string(), + klass_name->as_C_string(), name->as_C_string(), signature->as_C_string(), + rfi->is_resolved(Bytecodes::_getstatic) || rfi->is_resolved(Bytecodes::_putstatic) ? " *** static" : "", + (archived ? "" : " (resolution is not deterministic)")); + } } ArchiveBuilder::alloc_stats()->record_field_cp_entry(archived, resolved && !archived); } @@ -474,32 +477,40 @@ void ConstantPoolCache::remove_resolved_method_entries_if_non_deterministic() { rme->is_resolved(Bytecodes::_invokehandle) || (rme->is_resolved(Bytecodes::_invokestatic) && VM_Version::supports_fast_class_init_checks()); + const char* rejection_reason = nullptr; if (resolved && !CDSConfig::is_dumping_preimage_static_archive() - && can_archive_resolved_method(src_cp, rme)) { + && can_archive_resolved_method(src_cp, rme, rejection_reason)) { rme->mark_and_relocate(src_cp); archived = true; } else { rme->remove_unshareable_info(); } - LogStreamHandle(Trace, aot, resolve) log; - if (log.is_enabled()) { + LogTarget(Trace, aot, resolve) lt; + if (lt.is_enabled()) { ResourceMark rm; int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); Symbol* klass_name = cp->klass_name_at(klass_cp_index); Symbol* name = cp->uncached_name_ref_at(cp_index); Symbol* signature = cp->uncached_signature_ref_at(cp_index); - log.print("%s%s method CP entry [%3d]: %s %s.%s:%s", + LogStream ls(lt); + if (resolved) { + ls.print("%s%s method CP entry [%3d]: %s %s.%s:%s", (archived ? "archived" : "reverted"), (rme->is_resolved(Bytecodes::_invokeinterface) ? " interface" : ""), cp_index, cp->pool_holder()->name()->as_C_string(), klass_name->as_C_string(), name->as_C_string(), signature->as_C_string()); + if (rejection_reason != nullptr) { + ls.print(" %s", rejection_reason); + } + } if (archived) { Klass* resolved_klass = cp->resolved_klass_at(klass_cp_index); - log.print(" => %s%s", + ls.print(" => %s%s", resolved_klass->name()->as_C_string(), (rme->is_resolved(Bytecodes::_invokestatic) ? " *** static" : "")); } + ls.cr(); } ArchiveBuilder::alloc_stats()->record_method_cp_entry(archived, resolved && !archived); } @@ -528,42 +539,50 @@ void ConstantPoolCache::remove_resolved_indy_entries_if_non_deterministic() { Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref); Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref); Symbol* bsm_klass = cp->klass_name_at(cp->uncached_klass_ref_index_at(bsm_ref)); - log.print("%s indy CP entry [%3d]: %s (%d)", - (archived ? "archived" : "reverted"), - cp_index, cp->pool_holder()->name()->as_C_string(), i); - log.print(" %s %s.%s:%s", (archived ? "=>" : " "), bsm_klass->as_C_string(), - bsm_name->as_C_string(), bsm_signature->as_C_string()); + if (resolved) { + log.print("%s indy CP entry [%3d]: %s (%d)", + (archived ? "archived" : "reverted"), + cp_index, cp->pool_holder()->name()->as_C_string(), i); + log.print(" %s %s.%s:%s%s", (archived ? "=>" : " "), bsm_klass->as_C_string(), + bsm_name->as_C_string(), bsm_signature->as_C_string(), + (archived ? "" : " (resolution is not deterministic)")); + } } ArchiveBuilder::alloc_stats()->record_indy_cp_entry(archived, resolved && !archived); } } -bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry) { - LogStreamHandle(Trace, aot, resolve) log; +bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry, const char*& rejection_reason) { InstanceKlass* pool_holder = constant_pool()->pool_holder(); if (pool_holder->defined_by_other_loaders()) { // Archiving resolved cp entries for classes from non-builtin loaders // is not yet supported. + rejection_reason = "(pool holder comes from a non-builtin loader)"; return false; } if (CDSConfig::is_dumping_dynamic_archive()) { // InstanceKlass::methods() has been resorted. We need to // update the vtable_index in method_entry (not implemented) + rejection_reason = "(InstanceKlass::methods() has been resorted)"; return false; } if (!method_entry->is_resolved(Bytecodes::_invokevirtual)) { if (method_entry->method() == nullptr) { + rejection_reason = "(method entry is not resolved)"; return false; } if (method_entry->method()->is_continuation_native_intrinsic()) { + rejection_reason = "(corresponding stub is generated on demand during method resolution)"; return false; // FIXME: corresponding stub is generated on demand during method resolution (see LinkResolver::resolve_static_call). } if (method_entry->is_resolved(Bytecodes::_invokehandle) && !CDSConfig::is_dumping_method_handles()) { + rejection_reason = "(not dumping method handles)"; return false; } if (method_entry->method()->is_method_handle_intrinsic() && !CDSConfig::is_dumping_method_handles()) { + rejection_reason = "(not dumping intrinsic method handles)"; return false; } } @@ -572,6 +591,7 @@ bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, Resolv assert(src_cp->tag_at(cp_index).is_method() || src_cp->tag_at(cp_index).is_interface_method(), "sanity"); if (!AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { + rejection_reason = "(resolution is not deterministic)"; return false; } return true; diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp index 14202f226d1..f698f50d3a8 100644 --- a/src/hotspot/share/oops/cpCache.hpp +++ b/src/hotspot/share/oops/cpCache.hpp @@ -226,7 +226,7 @@ class ConstantPoolCache: public MetaspaceObj { void remove_resolved_field_entries_if_non_deterministic(); void remove_resolved_indy_entries_if_non_deterministic(); void remove_resolved_method_entries_if_non_deterministic(); - bool can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry); + bool can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry, const char*& rejection_reason); #endif // RedefineClasses support diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java index 4586b94b519..1089e849a90 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/AOTLinkedVarHandles.java @@ -64,6 +64,7 @@ public class AOTLinkedVarHandles { OutputAnalyzer dumpOut = CDSTestUtils.createArchiveAndCheck(opts); dumpOut.shouldMatch(s + "java/lang/invoke/VarHandle.compareAndExchangeAcquire:\\(\\[DIDI\\)D =>"); dumpOut.shouldMatch(s + "java/lang/invoke/VarHandle.get:\\(\\[DI\\)D => "); + dumpOut.shouldNotContain("rejected .* CP entry.*"); CDSOptions runOpts = (new CDSOptions()) .setUseVersion(false) From c4e39cea51faa01ec7dcd447c2e89ef988e6a7fb Mon Sep 17 00:00:00 2001 From: Ashay Rane <253344819+raneashay@users.noreply.github.com> Date: Mon, 2 Mar 2026 16:49:28 +0000 Subject: [PATCH 013/170] 8373635: C2: Wrong constant in GraphKit::basic_plus_adr() Reviewed-by: qamai, mhaessig --- src/hotspot/share/opto/graphKit.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 084b137f313..c969abb85bb 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -1177,7 +1177,21 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) { //------------------------------basic_plus_adr--------------------------------- Node* GraphKit::basic_plus_adr(Node* base, Node* ptr, Node* offset) { // short-circuit a common case - if (offset == intcon(0)) return ptr; + if (offset == MakeConX(0)) { + return ptr; + } +#ifdef ASSERT + // Both 32-bit and 64-bit zeros should have been handled by the previous `if` + // statement, so if we see either 32-bit or 64-bit zeros here, then we have a + // problem. + if (offset->is_Con()) { + const Type* t = offset->bottom_type(); + bool is_zero_int = t->isa_int() && t->is_int()->get_con() == 0; + bool is_zero_long = t->isa_long() && t->is_long()->get_con() == 0; + assert(!is_zero_int && !is_zero_long, + "Unexpected zero offset - should have matched MakeConX(0)"); + } +#endif return _gvn.transform( new AddPNode(base, ptr, offset) ); } From f2a52b7a069c9180638aec15cc0d748f337c3d2f Mon Sep 17 00:00:00 2001 From: William Kemper Date: Mon, 2 Mar 2026 17:02:22 +0000 Subject: [PATCH 014/170] 8378880: GenShen: Fix typo in recent conversion to atomic field Reviewed-by: kdnilsen, xpeng, ysr --- src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index d5e34d02b13..4fda65b4030 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -583,7 +583,7 @@ void ShenandoahOldGeneration::handle_failed_evacuation() { void ShenandoahOldGeneration::handle_failed_promotion(Thread* thread, size_t size) { _promotion_failure_count.add_then_fetch(1UL); - _promotion_failure_words.and_then_fetch(size); + _promotion_failure_words.add_then_fetch(size); LogTarget(Debug, gc, plab) lt; LogStream ls(lt); From 0baeccddffb0a99ce82a1bffdf209c8d2dc05f1c Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Mon, 2 Mar 2026 17:22:48 +0000 Subject: [PATCH 015/170] 8378111: Migrate java/util/jar tests to JUnit Reviewed-by: lancea --- .../util/jar/Attributes/IterationOrder.java | 28 ++- test/jdk/java/util/jar/Attributes/Name.java | 19 +- .../Attributes/NullAndEmptyKeysAndValues.java | 22 +- .../util/jar/Attributes/PutAndPutAll.java | 36 ++- .../java/util/jar/Attributes/TestAttrsNL.java | 57 +++-- .../jar/JarEntry/GetMethodsReturnClones.java | 36 ++- .../java/util/jar/JarFile/Constructor.java | 46 ++-- .../IgnoreUnrelatedSignatureFiles.java | 137 ++++++----- .../util/jar/JarFile/JarBacktickManifest.java | 27 ++- .../java/util/jar/JarFile/JarNoManifest.java | 23 +- test/jdk/java/util/jar/JarFile/MevNPE.java | 13 +- .../java/util/jar/JarFile/ScanSignedJar.java | 29 +-- .../JarFile/SignedJarFileGetInputStream.java | 41 ++-- .../jar/JarFile/SignedJarPendingBlock.java | 65 +++-- .../java/util/jar/JarFile/SorryClosed.java | 58 +++-- test/jdk/java/util/jar/JarFile/TurkCert.java | 37 ++- .../util/jar/JarFile/VerifySignedJar.java | 55 ++--- .../jarVerification/MultiProviderTest.java | 31 +-- .../jar/JarFile/mrjar/MultiReleaseJarAPI.java | 87 +++---- .../mrjar/MultiReleaseJarHttpProperties.java | 37 +-- .../mrjar/MultiReleaseJarProperties.java | 45 ++-- .../mrjar/MultiReleaseJarSecurity.java | 38 +-- .../JarFile/mrjar/TestVersionedStream.java | 99 ++++---- .../util/jar/JarInputStream/EmptyJar.java | 22 +- .../JarInputStream/ExtraFileInMetaInf.java | 22 +- .../jar/JarInputStream/ScanSignedJar.java | 24 +- .../TestIndexedJarWithBadSignature.java | 34 +-- .../util/jar/Manifest/CreateManifest.java | 47 ++-- .../jar/Manifest/IncludeInExceptionsTest.java | 64 +++-- .../util/jar/Manifest/LineBreakLineWidth.java | 31 +-- .../util/jar/Manifest/ValueUtf8Coding.java | 16 +- .../jar/Manifest/WriteBinaryStructure.java | 25 +- test/jdk/java/util/jar/TestExtra.java | 226 ++++-------------- test/jdk/java/util/jar/TestJarExtra.java | 224 +++++++++++++++++ 34 files changed, 990 insertions(+), 811 deletions(-) create mode 100644 test/jdk/java/util/jar/TestJarExtra.java diff --git a/test/jdk/java/util/jar/Attributes/IterationOrder.java b/test/jdk/java/util/jar/Attributes/IterationOrder.java index 4028d71e7c4..edd1d9b8bc8 100644 --- a/test/jdk/java/util/jar/Attributes/IterationOrder.java +++ b/test/jdk/java/util/jar/Attributes/IterationOrder.java @@ -1,5 +1,6 @@ /* * Copyright 2014 Google, Inc. All Rights Reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +25,26 @@ /* @test * @bug 8062194 * @summary Ensure Attribute iteration order is the insertion order. + * @run junit IterationOrder */ +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + import java.util.Arrays; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.fail; public class IterationOrder { - static void checkOrder(Attributes.Name k0, String v0, + + @ParameterizedTest + @MethodSource + void checkOrderTest(Attributes.Name k0, String v0, Attributes.Name k1, String v1, Attributes.Name k2, String v2) { Attributes x = new Attributes(); @@ -48,7 +60,7 @@ public class IterationOrder { && entries[1].getValue() == v1 && entries[2].getKey() == k2 && entries[2].getValue() == v2)) { - throw new AssertionError(Arrays.toString(entries)); + fail(Arrays.toString(entries)); } Object[] keys = x.keySet().toArray(); @@ -56,19 +68,21 @@ public class IterationOrder { && keys[0] == k0 && keys[1] == k1 && keys[2] == k2)) { - throw new AssertionError(Arrays.toString(keys)); + fail(Arrays.toString(keys)); } } - public static void main(String[] args) throws Exception { + static Stream checkOrderTest() { Attributes.Name k0 = Name.MANIFEST_VERSION; Attributes.Name k1 = Name.MAIN_CLASS; Attributes.Name k2 = Name.SEALED; String v0 = "42.0"; String v1 = "com.google.Hello"; String v2 = "yes"; - checkOrder(k0, v0, k1, v1, k2, v2); - checkOrder(k1, v1, k0, v0, k2, v2); - checkOrder(k2, v2, k1, v1, k0, v0); + return Stream.of( + Arguments.of(k0, v0, k1, v1, k2, v2), + Arguments.of(k1, v1, k0, v0, k2, v2), + Arguments.of(k2, v2, k1, v1, k0, v0) + ); } } diff --git a/test/jdk/java/util/jar/Attributes/Name.java b/test/jdk/java/util/jar/Attributes/Name.java index 78306028698..843038cb820 100644 --- a/test/jdk/java/util/jar/Attributes/Name.java +++ b/test/jdk/java/util/jar/Attributes/Name.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,20 @@ @bug 4199981 @summary Make sure empty string is not a valid Attributes name. - */ + @run junit Name + */ +import org.junit.jupiter.api.Test; import java.util.jar.Attributes; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class Name { - public static void main(String[] args) throws Exception { - try { - Attributes.Name name = new Attributes.Name(""); - throw new Exception("empty string should be rejected"); - } catch (IllegalArgumentException e) { - } + + @Test + void emptyStringTest() { + assertThrows(IllegalArgumentException.class, () -> new Attributes.Name(""), + "empty string should be rejected"); } } diff --git a/test/jdk/java/util/jar/Attributes/NullAndEmptyKeysAndValues.java b/test/jdk/java/util/jar/Attributes/NullAndEmptyKeysAndValues.java index c62ddcced8a..e99825d235e 100644 --- a/test/jdk/java/util/jar/Attributes/NullAndEmptyKeysAndValues.java +++ b/test/jdk/java/util/jar/Attributes/NullAndEmptyKeysAndValues.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,8 +21,6 @@ * questions. */ -import static java.nio.charset.StandardCharsets.UTF_8; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -31,14 +29,16 @@ import java.util.jar.Manifest; import java.util.jar.Attributes.Name; import java.lang.reflect.Field; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.*; /** * @test * @bug 8066619 * @modules java.base/java.util.jar:+open - * @run testng/othervm --enable-final-field-mutation=ALL-UNNAMED NullAndEmptyKeysAndValues + * @run junit/othervm --enable-final-field-mutation=ALL-UNNAMED NullAndEmptyKeysAndValues * @summary Tests manifests with {@code null} and empty string {@code ""} * values as section name, header name, or value in both main and named * attributes sections. @@ -108,7 +108,7 @@ public class NullAndEmptyKeysAndValues { attr.set(mf, mainAtts); mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0"); mf = writeAndRead(mf); - assertEquals(mf.getMainAttributes().getValue(SOME_KEY), NULL_TEXT); + assertEquals(NULL_TEXT, mf.getMainAttributes().getValue(SOME_KEY)); } @Test @@ -122,7 +122,7 @@ public class NullAndEmptyKeysAndValues { attr.set(mf, mainAtts); mf.getMainAttributes().put(Name.MANIFEST_VERSION, "1.0"); mf = writeAndRead(mf); - assertEquals(mf.getMainAttributes().getValue(SOME_KEY), EMPTY_STR); + assertEquals(EMPTY_STR, mf.getMainAttributes().getValue(SOME_KEY)); } @Test @@ -171,8 +171,7 @@ public class NullAndEmptyKeysAndValues { map.put(new Name(SOME_KEY), null); }}); mf = writeAndRead(mf); - assertEquals(mf.getEntries().get(SOME_KEY).getValue(SOME_KEY), - NULL_TEXT); + assertEquals(NULL_TEXT, mf.getEntries().get(SOME_KEY).getValue(SOME_KEY)); } @Test @@ -183,8 +182,7 @@ public class NullAndEmptyKeysAndValues { map.put(new Name(SOME_KEY), EMPTY_STR); }}); mf = writeAndRead(mf); - assertEquals(mf.getEntries().get(SOME_KEY).getValue(SOME_KEY), - EMPTY_STR); + assertEquals(EMPTY_STR, mf.getEntries().get(SOME_KEY).getValue(SOME_KEY)); } static Manifest writeAndRead(Manifest mf) throws IOException { diff --git a/test/jdk/java/util/jar/Attributes/PutAndPutAll.java b/test/jdk/java/util/jar/Attributes/PutAndPutAll.java index f459daf8c2e..bd61ba1e92d 100644 --- a/test/jdk/java/util/jar/Attributes/PutAndPutAll.java +++ b/test/jdk/java/util/jar/Attributes/PutAndPutAll.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,31 +25,27 @@ @bug 4165833 4167600 @summary Test if put and putAll will test for illegal arguments. - */ + @run junit PutAndPutAll + */ +import org.junit.jupiter.api.Test; + import java.util.jar.Attributes; import java.util.HashMap; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class PutAndPutAll { - public static void main(String[] args) throws Exception { + + @Test + void classCastTest() { Attributes at = new Attributes(); - try{ - at.put("this is not an Attributes.Name", "value"); - throw new Exception("put should check for non Attributes.Name names"); - } catch (ClassCastException e) { - } - - try{ - at.put(new Attributes.Name("name"), new Integer(0)); - throw new Exception("put should check for non String values"); - } catch (ClassCastException e) { - } - - try { - at.putAll(new HashMap()); - throw new Exception("putAll should check for non Attributes maps"); - } catch (ClassCastException e) { - } + assertThrows(ClassCastException.class, + () -> at.put("this is not an Attributes.Name", "value"), "put should check for non Attributes.Name names"); + assertThrows(ClassCastException.class, + () -> at.put(new Attributes.Name("name"), new Integer(0)), "put should check for non String values"); + assertThrows(ClassCastException.class, + () -> at.putAll(new HashMap()), "putAll should check for non Attributes maps"); } } diff --git a/test/jdk/java/util/jar/Attributes/TestAttrsNL.java b/test/jdk/java/util/jar/Attributes/TestAttrsNL.java index 34f7e4c4502..abfd3df6cd7 100644 --- a/test/jdk/java/util/jar/Attributes/TestAttrsNL.java +++ b/test/jdk/java/util/jar/Attributes/TestAttrsNL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,28 @@ /* @test * @bug 8200530 * @summary Test Attributes newline + * @run junit TestAttrsNL */ +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; import java.util.jar.Manifest; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; import java.io.ByteArrayInputStream; import java.util.Map; +import java.util.stream.Stream; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class TestAttrsNL { - public static void main(String[] args) throws Throwable { + static Stream newLineAttributesTest() throws IOException { String manifestStr = "Manifest-Version: 1.0\r\n" + @@ -68,16 +77,16 @@ public class TestAttrsNL { new Name("key44"), "value44" ); - test(new Manifest(new ByteArrayInputStream(manifestStr.getBytes(UTF_8))), - mainAttrsExped, attrsExped); + var normal = Arguments.of(new Manifest(new ByteArrayInputStream(manifestStr.getBytes(UTF_8))), + mainAttrsExped, attrsExped); - test(new Manifest(new ByteArrayInputStream( - manifestStr.replaceAll("\r\n", "\r").getBytes(UTF_8))), - mainAttrsExped, attrsExped); + var carriage = Arguments.of(new Manifest(new ByteArrayInputStream( + manifestStr.replaceAll("\r\n", "\r").getBytes(UTF_8))), + mainAttrsExped, attrsExped); - test(new Manifest(new ByteArrayInputStream( - manifestStr.replaceAll("\r\n", "\n").getBytes(UTF_8))), - mainAttrsExped, attrsExped); + var newLine = Arguments.of(new Manifest(new ByteArrayInputStream( + manifestStr.replaceAll("\r\n", "\n").getBytes(UTF_8))), + mainAttrsExped, attrsExped); // mixed manifestStr = @@ -93,31 +102,33 @@ public class TestAttrsNL { "key22: value22\n END\r\n" + "key33: value33\r \n" + "key44: value44\n"; - test(new Manifest(new ByteArrayInputStream(manifestStr.getBytes(UTF_8))), + var mixed = Arguments.of(new Manifest(new ByteArrayInputStream(manifestStr.getBytes(UTF_8))), mainAttrsExped, attrsExped); - + return Stream.of(normal, carriage, newLine, mixed); } - private static void test(Manifest m, + @ParameterizedTest + @MethodSource + void newLineAttributesTest(Manifest m, Map mainAttrsExped, Map attrsExped) { Attributes mainAttrs = m.getMainAttributes(); mainAttrsExped.forEach( (k, v) -> { - if (!mainAttrs.containsKey(k) || !mainAttrs.get(k).equals(v)) { - System.out.printf(" containsKey(%s) : %b%n", k, mainAttrs.containsKey(k)); - System.out.printf(" get(%s) : %s%n", k, mainAttrs.get(k)); - throw new RuntimeException("expected attr: k=<" + k + ">, v=<" + v + ">"); - } + var expectedMsg = "expected attr: k=<" + k + ">, v=<" + v + ">"; + assertTrue(mainAttrs.containsKey(k), + " containsKey(%s) : %b%n%s".formatted(k, mainAttrs.containsKey(k), expectedMsg)); + assertEquals(v, mainAttrs.get(k), + " get(%s) : %s%n%s".formatted(k, mainAttrs.get(k), expectedMsg)); }); Attributes attrs = m.getAttributes("Hello"); attrs.forEach( (k, v) -> { - if (!attrs.containsKey(k) || !attrs.get(k).equals(v)) { - System.out.printf(" containsKey(%s) : %b%n", k, attrs.containsKey(k)); - System.out.printf(" get(%s) : %s%n", k, attrs.get(k)); - throw new RuntimeException("expected attr: k=<" + k + ">, v=<" + v + ">"); - } + var expectedMsg = "expected attr: k=<" + k + ">, v=<" + v + ">"; + assertTrue(attrs.containsKey(k), + " containsKey(%s) : %b%n%s".formatted(k, attrs.containsKey(k), expectedMsg)); + assertEquals(v, attrs.get(k), + " get(%s) : %s%n%s".formatted(k, attrs.get(k), expectedMsg)); }); } } diff --git a/test/jdk/java/util/jar/JarEntry/GetMethodsReturnClones.java b/test/jdk/java/util/jar/JarEntry/GetMethodsReturnClones.java index 3c4f06dd6f0..a9b35220de3 100644 --- a/test/jdk/java/util/jar/JarEntry/GetMethodsReturnClones.java +++ b/test/jdk/java/util/jar/JarEntry/GetMethodsReturnClones.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,20 +26,28 @@ * @bug 6337925 * @summary Ensure that callers cannot modify the internal JarEntry cert and * codesigner arrays. - * @author Sean Mullan + * @run junit GetMethodsReturnClones */ +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; import java.io.InputStream; import java.security.CodeSigner; import java.security.cert.Certificate; import java.util.*; import java.util.jar.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class GetMethodsReturnClones { private static final String BASE = System.getProperty("test.src", ".") + System.getProperty("file.separator"); + private static List jarEntries; - public static void main(String[] args) throws Exception { + @BeforeAll() + static void setupEntries() throws IOException { List entries = new ArrayList<>(); try (JarFile jf = new JarFile(BASE + "test.jar", true)) { byte[] buffer = new byte[8192]; @@ -55,23 +63,29 @@ public class GetMethodsReturnClones { } } } + jarEntries = entries; + } - for (JarEntry je : entries) { + @Test + void certsTest() { + for (JarEntry je : jarEntries) { Certificate[] certs = je.getCertificates(); - CodeSigner[] signers = je.getCodeSigners(); if (certs != null) { certs[0] = null; certs = je.getCertificates(); - if (certs[0] == null) { - throw new Exception("Modified internal certs array"); - } + assertNotNull(certs[0], "Modified internal certs array"); } + } + } + + @Test + void signersTest() { + for (JarEntry je : jarEntries) { + CodeSigner[] signers = je.getCodeSigners(); if (signers != null) { signers[0] = null; signers = je.getCodeSigners(); - if (signers[0] == null) { - throw new Exception("Modified internal codesigners array"); - } + assertNotNull(signers[0], "Modified internal codesigners array"); } } } diff --git a/test/jdk/java/util/jar/JarFile/Constructor.java b/test/jdk/java/util/jar/JarFile/Constructor.java index 8c1a8623e61..071c68fdd9e 100644 --- a/test/jdk/java/util/jar/JarFile/Constructor.java +++ b/test/jdk/java/util/jar/JarFile/Constructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,55 +21,45 @@ * questions. */ -/** +/* * @test * @bug 4842702 8211765 * @summary Check that constructors throw specified exceptions - * @author Martin Buchholz + * @run junit Constructor */ +import org.junit.jupiter.api.Test; + import java.util.jar.JarFile; import java.io.File; import java.io.IOException; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class Constructor { - private static void Unreached (Object o) - throws Exception - { - // Should never get here - throw new Exception ("Expected exception was not thrown"); - } - public static void main(String[] args) - throws Exception - { - try { Unreached (new JarFile ((File) null, true, JarFile.OPEN_READ)); } - catch (NullPointerException e) {} + @Test + void constructorTest() { - try { Unreached (new JarFile ((File) null, true)); } - catch (NullPointerException e) {} + assertThrows(NullPointerException.class, () -> new JarFile ((File) null, true, JarFile.OPEN_READ)); - try { Unreached (new JarFile ((File) null)); } - catch (NullPointerException e) {} + assertThrows(NullPointerException.class, () -> new JarFile ((File) null, true)); - try { Unreached (new JarFile ((String) null, true)); } - catch (NullPointerException e) {} + assertThrows(NullPointerException.class, () -> new JarFile ((File) null)); - try { Unreached (new JarFile ((String) null)); } - catch (NullPointerException e) {} + assertThrows(NullPointerException.class, () -> new JarFile ((String) null, true)); - try { Unreached (new JarFile ("NoSuchJar.jar")); } - catch (IOException e) {} + assertThrows(NullPointerException.class, () -> new JarFile ((String) null)); - try { Unreached (new JarFile (new File ("NoSuchJar.jar"))); } - catch (IOException e) {} + assertThrows(IOException.class, () -> new JarFile ("NoSuchJar.jar")); + + assertThrows(IOException.class, () -> new JarFile (new File ("NoSuchJar.jar"))); // Test that an IOExcception is thrown when an invalid charater // is part of the path on Windows and Unix final String invalidOSPath = System.getProperty("os.name") .startsWith("Windows") ? "C:\\*" : "foo\u0000bar"; - try { Unreached (new JarFile (invalidOSPath)); } - catch (IOException e) {} + assertThrows(IOException.class, () -> new JarFile (invalidOSPath)); } } diff --git a/test/jdk/java/util/jar/JarFile/IgnoreUnrelatedSignatureFiles.java b/test/jdk/java/util/jar/JarFile/IgnoreUnrelatedSignatureFiles.java index 0f55702c1f6..e5a32dfde73 100644 --- a/test/jdk/java/util/jar/JarFile/IgnoreUnrelatedSignatureFiles.java +++ b/test/jdk/java/util/jar/JarFile/IgnoreUnrelatedSignatureFiles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,7 @@ * questions. */ -/** +/* * @test * @bug 8300140 * @summary Make sure signature related files in subdirectories of META-INF are not considered for verification @@ -29,12 +29,14 @@ * @modules java.base/sun.security.util * @modules java.base/sun.security.tools.keytool * @modules jdk.jartool/sun.security.tools.jarsigner - * @run main/othervm IgnoreUnrelatedSignatureFiles + * @run junit/othervm IgnoreUnrelatedSignatureFiles */ import jdk.internal.access.JavaUtilZipFileAccess; import jdk.internal.access.SharedSecrets; import jdk.security.jarsigner.JarSigner; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import sun.security.tools.jarsigner.Main; import sun.security.util.SignatureFileVerifier; @@ -62,6 +64,10 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class IgnoreUnrelatedSignatureFiles { private static final JavaUtilZipFileAccess JUZA = SharedSecrets.getJavaUtilZipFileAccess(); @@ -69,56 +75,76 @@ public class IgnoreUnrelatedSignatureFiles { // This path resides in a subdirectory of META-INF, so it should not be considered signature related public static final String SUBDIR_SF_PATH = "META-INF/subdirectory/META-INF/SIGNER.SF"; + // Jars used for testing. See `setupJars` below for setup + static Path j; + static Path s; + static Path m; + static Path sm; + static Path ca; + static Path cas; - public static void main(String[] args) throws Exception { - + @BeforeAll + static void setupJars() throws Exception { // Regular signed JAR - Path j = createJarFile(); - Path s = signJarFile(j, "SIGNER1", "signed"); + j = createJarFile(); + s = signJarFile(j, "SIGNER1", "signed"); // Singed JAR with unrelated signature files - Path m = moveSignatureRelated(s); - Path sm = signJarFile(m, "SIGNER2", "modified-signed"); + m = moveSignatureRelated(s); + sm = signJarFile(m, "SIGNER2", "modified-signed"); // Signed JAR with custom SIG-* files - Path ca = createCustomAlgJar(); - Path cas = signJarFile(ca, "SIGNER1", "custom-signed"); + ca = createCustomAlgJar(); + cas = signJarFile(ca, "SIGNER1", "custom-signed"); + } - // 0: Sanity check that the basic signed JAR verifies + // Sanity check that the basic signed JAR verifies + @Test + void signedJarVerifyTest() throws IOException { try (JarFile jf = new JarFile(s.toFile(), true)) { Map entries = jf.getManifest().getEntries(); - if (entries.size() != 1) { - throw new Exception("Expected a single manifest entry for the digest of a.txt, instead found entries: " + entries.keySet()); - } + assertEquals(1, entries.size(), + "Expected a single manifest entry for the digest of a.txt, instead found entries: " + entries.keySet()); JarEntry entry = jf.getJarEntry("a.txt"); try (InputStream in = jf.getInputStream(entry)) { in.transferTo(OutputStream.nullOutputStream()); } } - // 1: Check ZipFile.Source.isSignatureRelated + } + + // Check ZipFile.Source.isSignatureRelated + @Test + void zipFileSourceIsSignatureRelatedTest() throws IOException { try (JarFile jarFile = new JarFile(m.toFile())) { List manifestAndSignatureRelatedFiles = JUZA.getManifestAndSignatureRelatedFiles(jarFile); for (String signatureRelatedFile : manifestAndSignatureRelatedFiles) { String dir = signatureRelatedFile.substring(0, signatureRelatedFile.lastIndexOf("/")); - if (!"META-INF".equals(dir)) { - throw new Exception("Signature related file does not reside directly in META-INF/ : " + signatureRelatedFile); - } + assertEquals("META-INF", dir, + "Signature related file does not reside directly in META-INF/ : " + signatureRelatedFile); } } + } - // 2: Check SignatureFileVerifier.isSigningRelated - if (SignatureFileVerifier.isSigningRelated(SUBDIR_SF_PATH)) { - throw new Exception("Signature related file does not reside directly in META-INF/ : " + SUBDIR_SF_PATH); - } + // Check SignatureFileVerifier.isSigningRelated + @Test + void sigFileVerifierIsSigningRelatedTest() { + assertFalse(SignatureFileVerifier.isSigningRelated(SUBDIR_SF_PATH), + "Signature related file does not reside directly in META-INF/ : " + SUBDIR_SF_PATH); + } - // 3: Check JarInputStream with doVerify = true + // Check JarInputStream with doVerify = true + @Test + void jarIStreamDoVerifyTest() throws IOException { try (JarInputStream in = new JarInputStream(Files.newInputStream(m), true)) { - while (in.getNextEntry() != null) { + while (in.getNextEntry() != null) { in.transferTo(OutputStream.nullOutputStream()); } } + } - // 4: Check that a JAR containing unrelated .SF, .RSA files is signed as-if it is unsigned + // Check that a JAR containing unrelated .SF, .RSA files is signed as-if it is unsigned + @Test + void unrelatedFilesUnsignedTest() throws IOException { try (ZipFile zf = new ZipFile(sm.toFile())) { ZipEntry mf = zf.getEntry("META-INF/MANIFEST.MF"); try (InputStream stream = zf.getInputStream(mf)) { @@ -126,19 +152,24 @@ public class IgnoreUnrelatedSignatureFiles { // When JarSigner considers a jar to not be already signed, // the 'Manifest-Version' attributed name will be case-normalized // Assert that manifest-version is not in lowercase - if (manifest.startsWith("manifest-version")) { - throw new Exception("JarSigner unexpectedly treated unsigned jar as signed"); - } + assertFalse(manifest.startsWith("manifest-version"), + "JarSigner unexpectedly treated unsigned jar as signed"); } } + } - // 5: Check that a JAR containing non signature related .SF, .RSA files can be signed + // Check that a JAR containing non signature related .SF, .RSA files can be signed + @Test + void nonSigFileIsSignableTest() throws Exception { try (JarFile jf = new JarFile(sm.toFile(), true)) { checkSignedBy(jf, "a.txt", "CN=SIGNER2"); checkSignedBy(jf, "META-INF/subdirectory/META-INF/SIGNER1.SF", "CN=SIGNER2"); } + } - // 6: Check that JarSigner does not move unrelated [SF,RSA] files to the beginning of signed JARs + // Check that JarSigner does not move unrelated [SF,RSA] files to the beginning of signed JARs + @Test + void jarSignerDoesNotMoveUnrelatedTest() throws IOException { try (JarFile zf = new JarFile(sm.toFile())) { List actualOrder = zf.stream().map(ZipEntry::getName).toList(); @@ -154,23 +185,25 @@ public class IgnoreUnrelatedSignatureFiles { "META-INF/subdirectory2/META-INF/SIGNER1.RSA" ); - if (!expectedOrder.equals(actualOrder)) { - String msg = (""" + assertEquals(expectedOrder, actualOrder, (""" Unexpected file order in JAR with unrelated SF,RSA files Expected order: %s Actual order: %s""") - .formatted(expectedOrder, actualOrder); - throw new Exception(msg); - } + .formatted(expectedOrder, actualOrder)); } + } - // 7: Check that jarsigner ignores unrelated signature files + // Check that jarsigner ignores unrelated signature files + @Test + void jarSignerIgnoresUnrelatedTest() throws Exception { String message = jarSignerVerify(m); - if (message.contains("WARNING")) { - throw new Exception("jarsigner output contains unexpected warning: " +message); - } + assertFalse(message.contains("WARNING"), + "jarsigner output contains unexpected warning: " + message); + } - // 8: Check that SignatureFileVerifier.isSigningRelated handles custom SIG-* files correctly + // Check that SignatureFileVerifier.isSigningRelated handles custom SIG-* files correctly + @Test + void customSIGFilesTest() throws IOException { try (JarFile jf = new JarFile(cas.toFile(), true)) { // These files are not signature-related and should be signed @@ -185,10 +218,9 @@ public class IgnoreUnrelatedSignatureFiles { Set actualSigned = jf.getManifest().getEntries().keySet(); - if (!expectedSigned.equals(actualSigned)) { - throw new Exception("Unexpected MANIFEST entries. Expected %s, got %s" - .formatted(expectedSigned, actualSigned)); - } + assertEquals(expectedSigned, actualSigned, + "Unexpected MANIFEST entries. Expected %s, got %s" + .formatted(expectedSigned, actualSigned)); } } @@ -220,22 +252,17 @@ public class IgnoreUnrelatedSignatureFiles { // Verify that the entry is signed CodeSigner[] signers = je.getCodeSigners(); - if (signers == null) { - throw new Exception(String.format("Expected %s to be signed", name)); - } + assertNotNull(signers, "Expected %s to be signed".formatted(name)); // There should be a single signer - if (signers.length != 1) { - throw new Exception(String.format("Expected %s to be signed by exactly one signer", name)); - } + assertEquals(1, signers.length, + "Expected %s to be signed by exactly one signer".formatted(name)); String actualSigner = ((X509Certificate) signers[0] .getSignerCertPath().getCertificates().get(0)) .getIssuerX500Principal().getName(); - - if (!actualSigner.equals(expectedSigner)) { - throw new Exception(String.format("Expected %s to be signed by %s, was signed by %s", name, expectedSigner, actualSigner)); - } + assertEquals(expectedSigner, actualSigner, + "Expected %s to be signed by %s, was signed by %s".formatted(name, expectedSigner, actualSigner)); } /** diff --git a/test/jdk/java/util/jar/JarFile/JarBacktickManifest.java b/test/jdk/java/util/jar/JarFile/JarBacktickManifest.java index 65d54a67a47..66edf3ae3ee 100644 --- a/test/jdk/java/util/jar/JarFile/JarBacktickManifest.java +++ b/test/jdk/java/util/jar/JarFile/JarBacktickManifest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @summary Make sure scanning manifest doesn't throw AIOOBE on certain strings containing backticks. * @library /test/lib/ * @build jdk.test.lib.util.JarBuilder - * @run testng JarBacktickManifest + * @run junit JarBacktickManifest */ import java.io.File; @@ -35,19 +35,20 @@ import java.io.IOException; import java.nio.file.Files; import java.util.jar.JarFile; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - import jdk.test.lib.util.JarBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; + public class JarBacktickManifest { public static final String VERIFY_MANIFEST_JAR = "verifyManifest.jar"; - @BeforeClass - public void initialize() throws Exception { + @BeforeAll + public static void initialize() throws Exception { JarBuilder jb = new JarBuilder(VERIFY_MANIFEST_JAR); jb.addAttribute("Test", " Class-`Path` "); jb.addAttribute("Test2", " Multi-`Release "); @@ -55,14 +56,14 @@ public class JarBacktickManifest { } @Test - public void test() throws Exception { + public void backtickTest() throws Exception { try (JarFile jf = new JarFile(VERIFY_MANIFEST_JAR)) { // do not set runtime versioning - Assert.assertFalse(jf.isMultiRelease(), "Shouldn't be multi-release"); + assertFalse(jf.isMultiRelease(), "Shouldn't be multi-release"); } } - @AfterClass - public void close() throws IOException { + @AfterAll + public static void close() throws IOException { Files.delete(new File(VERIFY_MANIFEST_JAR).toPath()); } } diff --git a/test/jdk/java/util/jar/JarFile/JarNoManifest.java b/test/jdk/java/util/jar/JarFile/JarNoManifest.java index 971ce92f9e9..31301e28975 100644 --- a/test/jdk/java/util/jar/JarFile/JarNoManifest.java +++ b/test/jdk/java/util/jar/JarFile/JarNoManifest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,18 +24,25 @@ /* @test @bug 4771616 @summary JarFile.maybeInstantiateVerifier must check for absence of manifest + @run junit JarNoManifest */ +import org.junit.jupiter.api.Test; + import java.io.*; import java.util.jar.*; import java.util.zip.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + public class JarNoManifest { - public static void main(String[] args) throws Exception { - File f = new File(System.getProperty("test.src","."), "no-manifest.jar"); - JarFile jar = new JarFile(f); - ZipEntry entry = jar.getEntry("JarNoManifest.java"); - // The following throws a NullPointerException when the bug is present - InputStream in = jar.getInputStream(entry); - } + + @Test + void absentManifestTest() throws IOException { + File f = new File(System.getProperty("test.src", "."), "no-manifest.jar"); + JarFile jar = new JarFile(f); + ZipEntry entry = jar.getEntry("JarNoManifest.java"); + // The following throws a NullPointerException when the bug is present + assertDoesNotThrow(() -> jar.getInputStream(entry)); + } } diff --git a/test/jdk/java/util/jar/JarFile/MevNPE.java b/test/jdk/java/util/jar/JarFile/MevNPE.java index f8627d33324..20ac9f2d796 100644 --- a/test/jdk/java/util/jar/JarFile/MevNPE.java +++ b/test/jdk/java/util/jar/JarFile/MevNPE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,22 +24,27 @@ /* @test * @bug 7023056 * @summary NPE from sun.security.util.ManifestEntryVerifier.verify during Maven build + * @run junit MevNPE */ +import org.junit.jupiter.api.Test; + import java.io.*; import java.util.jar.*; public class MevNPE { - public static void main(String[] args) throws Exception { + + @Test + void noNpeTest() throws IOException { File f = new File(System.getProperty("test.src", "."), "Signed.jar"); try (JarFile jf = new JarFile(f, true)) { try (InputStream s1 = jf.getInputStream( jf.getJarEntry(JarFile.MANIFEST_NAME))) { s1.read(new byte[10000]); - }; + } try (InputStream s2 = jf.getInputStream( jf.getJarEntry(JarFile.MANIFEST_NAME))) { s2.read(new byte[10000]); - }; + } } } } diff --git a/test/jdk/java/util/jar/JarFile/ScanSignedJar.java b/test/jdk/java/util/jar/JarFile/ScanSignedJar.java index fe49cea24aa..75b4732645d 100644 --- a/test/jdk/java/util/jar/JarFile/ScanSignedJar.java +++ b/test/jdk/java/util/jar/JarFile/ScanSignedJar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,29 +21,35 @@ * questions. */ -/** +/* * @test * @bug 4953126 * @summary Check that a signed JAR file containing an unsupported signer info * attribute can be parsed successfully. + * @run junit ScanSignedJar */ +import org.junit.jupiter.api.Test; + import java.io.File; +import java.io.IOException; import java.io.InputStream; -import java.security.cert.Certificate; import java.util.Enumeration; import java.util.jar.*; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class ScanSignedJar { - public static void main(String[] args) throws Exception { + @Test + void unsupportedSignerTest() throws IOException { boolean isSigned = false; try (JarFile file = new JarFile(new File(System.getProperty("test.src","."), - "bogus-signerinfo-attr.jar"))) { + "bogus-signerinfo-attr.jar"))) { byte[] buffer = new byte[8192]; - for (Enumeration entries = file.entries(); entries.hasMoreElements();) { - JarEntry entry = (JarEntry) entries.nextElement(); + for (Enumeration entries = file.entries(); entries.hasMoreElements();) { + JarEntry entry = entries.nextElement(); try (InputStream jis = file.getInputStream(entry)) { while (jis.read(buffer, 0, buffer.length) != -1) { // read the jar entry @@ -53,14 +59,9 @@ public class ScanSignedJar { isSigned = true; } System.out.println((isSigned ? "[signed] " : "\t ") + - entry.getName()); + entry.getName()); } } - - if (isSigned) { - System.out.println("\nJAR file has signed entries"); - } else { - throw new Exception("Failed to detect that the JAR file is signed"); - } + assertTrue(isSigned, "Failed to detect that the JAR file is signed"); } } diff --git a/test/jdk/java/util/jar/JarFile/SignedJarFileGetInputStream.java b/test/jdk/java/util/jar/JarFile/SignedJarFileGetInputStream.java index 84ad357079d..9e524d5afd0 100644 --- a/test/jdk/java/util/jar/JarFile/SignedJarFileGetInputStream.java +++ b/test/jdk/java/util/jar/JarFile/SignedJarFileGetInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,45 +24,38 @@ /* @test * @bug 4845692 8206863 * @summary JarFile.getInputStream should not throw when jar file is signed - * @author Martin Buchholz + * @run junit SignedJarFileGetInputStream */ +import org.junit.jupiter.api.Test; + import java.io.*; import java.util.*; import java.util.jar.*; import java.util.zip.*; -public class SignedJarFileGetInputStream { - public static void main(String args[]) throws Throwable { - JarFile jar = new JarFile( - new File(System.getProperty("test.src", "."), "Signed.jar")); +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +public class SignedJarFileGetInputStream { + + @Test + void signedJarTest() throws IOException { + JarFile jar = new JarFile( + new File(System.getProperty("test.src", "."), "Signed.jar")); for (Enumeration e = jar.entries(); e.hasMoreElements();) { JarEntry entry = (JarEntry) e.nextElement(); - InputStream is = jar.getInputStream(new ZipEntry(entry.getName())); + InputStream is = assertDoesNotThrow(() -> jar.getInputStream(new ZipEntry(entry.getName()))); is.close(); } - // read(), available() on closed stream should throw IOException InputStream is = jar.getInputStream(new ZipEntry("Test.class")); is.close(); byte[] buffer = new byte[1]; - try { - is.read(); - throw new AssertionError("Should have thrown IOException"); - } catch (IOException success) {} - try { - is.read(buffer); - throw new AssertionError("Should have thrown IOException"); - } catch (IOException success) {} - try { - is.read(buffer, 0, buffer.length); - throw new AssertionError("Should have thrown IOException"); - } catch (IOException success) {} - try { - is.available(); - throw new AssertionError("Should have thrown IOException"); - } catch (IOException success) {} + assertThrows(IOException.class, () -> is.read()); + assertThrows(IOException.class, () -> is.read(buffer)); + assertThrows(IOException.class, () -> is.read(buffer, 0, buffer.length)); + assertThrows(IOException.class, () -> is.available()); } } diff --git a/test/jdk/java/util/jar/JarFile/SignedJarPendingBlock.java b/test/jdk/java/util/jar/JarFile/SignedJarPendingBlock.java index a6f9955a507..a6326be622a 100644 --- a/test/jdk/java/util/jar/JarFile/SignedJarPendingBlock.java +++ b/test/jdk/java/util/jar/JarFile/SignedJarPendingBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,21 @@ * questions. */ -/** +/* * @test * @modules java.base/sun.security.tools.keytool * @summary JARs with pending block files (where .RSA comes before .SF) should verify correctly + * @run junit SignedJarPendingBlock */ import jdk.security.jarsigner.JarSigner; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.FieldSource; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; @@ -42,32 +48,47 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class SignedJarPendingBlock { - public static void main(String[] args) throws Exception { + static Path signed; + static Path pendingBlocks; + static Path invalid; + + // Construct the test data + @BeforeAll + static void setup() throws Exception { Path jar = createJarFile(); - Path signed = signJarFile(jar); - Path pendingBlocks = moveBlockFirst(signed); - Path invalid = invalidate(pendingBlocks); - - // 1: Regular signed JAR with no pending blocks should verify - checkSigned(signed); - - // 2: Signed jar with pending blocks should verify - checkSigned(pendingBlocks); - - // 3: Invalid signed jar with pending blocks should throw SecurityException - try { - checkSigned(invalid); - throw new Exception("Expected invalid digest to be detected"); - } catch (SecurityException se) { - // Ignore - } + signed = signJarFile(jar); + pendingBlocks = moveBlockFirst(signed); + invalid = invalidate(pendingBlocks); } - private static void checkSigned(Path b) throws Exception { - try (JarFile jf = new JarFile(b.toFile(), true)) { + // Regular signed JAR with no pending blocks should verify + @Test + void checkValidSignedJar() { + assertDoesNotThrow(() -> checkSigned(signed), + "Valid digest should not fail"); + } + // Signed jar with pending blocks should verify + @Test + void checkValidSignedPendingJar() { + assertDoesNotThrow(() -> checkSigned(pendingBlocks), + "Valid digest should not fail"); + } + + // Invalid signed jar with pending blocks should throw SecurityException + @Test + void checkInvalidSignedJar() { + assertThrows(SecurityException.class, () -> checkSigned(invalid), + "Expected invalid digest to be detected"); + } + + private static void checkSigned(Path b) throws IOException { + try (JarFile jf = new JarFile(b.toFile(), true)) { JarEntry je = jf.getJarEntry("a.txt"); try (InputStream in = jf.getInputStream(je)) { in.transferTo(OutputStream.nullOutputStream()); diff --git a/test/jdk/java/util/jar/JarFile/SorryClosed.java b/test/jdk/java/util/jar/JarFile/SorryClosed.java index 19481347394..38950539c57 100644 --- a/test/jdk/java/util/jar/JarFile/SorryClosed.java +++ b/test/jdk/java/util/jar/JarFile/SorryClosed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,43 +24,49 @@ /* @test * @bug 4910572 * @summary Accessing a closed jar file should generate IllegalStateException. - * @author Martin Buchholz + * @run junit SorryClosed */ +import org.junit.jupiter.api.Test; + import java.io.IOException; import java.io.File; import java.util.jar.JarFile; import java.util.zip.ZipEntry; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class SorryClosed { - public static void main(String args[]) throws IOException { - File file = new File(System.getProperty("test.src","."), "test.jar"); - String testEntryName = "test.class"; + private static final File file = new File(System.getProperty("test.src", "."), "test.jar"); + private static final String testEntryName = "test.class"; - try { - JarFile f = new JarFile(file); - ZipEntry e = f.getEntry(testEntryName); - f.close(); - f.getInputStream(e); - } catch (IllegalStateException e) {} // OK + @Test + void getInputStreamTest() throws IOException { + JarFile f = new JarFile(file); + ZipEntry e = f.getEntry(testEntryName); + f.close(); + assertThrows(IllegalStateException.class, () -> f.getInputStream(e)); + } - try { - JarFile f = new JarFile(file); - f.close(); - f.getEntry(testEntryName); - } catch (IllegalStateException e) {} // OK + @Test + void getEntryTest() throws IOException { + JarFile f = new JarFile(file); + f.close(); + assertThrows(IllegalStateException.class, () -> f.getEntry(testEntryName)); + } - try { - JarFile f = new JarFile(file); - f.close(); - f.getJarEntry(testEntryName); - } catch (IllegalStateException e) {} // OK + @Test + void getJarEntryTest() throws IOException { + JarFile f = new JarFile(file); + f.close(); + assertThrows(IllegalStateException.class, () -> f.getJarEntry(testEntryName)); + } - try { - JarFile f = new JarFile(file); - f.close(); - f.getManifest(); - } catch (IllegalStateException e) {} // OK + @Test + void getManifestTest() throws IOException { + JarFile f = new JarFile(file); + f.close(); + assertThrows(IllegalStateException.class, f::getManifest); } } diff --git a/test/jdk/java/util/jar/JarFile/TurkCert.java b/test/jdk/java/util/jar/JarFile/TurkCert.java index 68e3d83e002..216fd535e2b 100644 --- a/test/jdk/java/util/jar/JarFile/TurkCert.java +++ b/test/jdk/java/util/jar/JarFile/TurkCert.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,38 +21,35 @@ * questions. */ -/** +/* * @test * @bug 4624534 * @summary Make sure jar certificates work for Turkish locale - * @author kladko + * @run junit/othervm -Duser.language=tr -Duser.country=TR TurkCert */ +import org.junit.jupiter.api.Test; + import java.util.*; import java.util.jar.*; import java.security.cert.*; import java.io.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class TurkCert { - public static void main(String[] args) throws Exception{ - Locale reservedLocale = Locale.getDefault(); - try { - Locale.setDefault(Locale.of("tr", "TR")); - File f = new File(System.getProperty("test.src","."), "test.jar"); - try (JarFile jf = new JarFile(f, true)) { - JarEntry je = (JarEntry)jf.getEntry("test.class"); - try (InputStream is = jf.getInputStream(je)) { - byte[] b = new byte[1024]; - while (is.read(b) != -1) { - } - } - if (je.getCertificates() == null) { - throw new Exception("Null certificate for test.class."); + + @Test + void turkishLocaleTest() throws IOException { + File f = new File(System.getProperty("test.src", "."), "test.jar"); + try (JarFile jf = new JarFile(f, true)) { + JarEntry je = (JarEntry)jf.getEntry("test.class"); + try (InputStream is = jf.getInputStream(je)) { + byte[] b = new byte[1024]; + while (is.read(b) != -1) { } } - } finally { - // restore the default locale - Locale.setDefault(reservedLocale); + assertNotNull(je.getCertificates(), "Null certificate for test.class."); } } } diff --git a/test/jdk/java/util/jar/JarFile/VerifySignedJar.java b/test/jdk/java/util/jar/JarFile/VerifySignedJar.java index bd5490502c9..e1602c0aa46 100644 --- a/test/jdk/java/util/jar/JarFile/VerifySignedJar.java +++ b/test/jdk/java/util/jar/JarFile/VerifySignedJar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,18 +21,20 @@ * questions. */ -/** +/* * @test - * @library /test/lib * @modules java.base/sun.security.x509 * @modules java.base/sun.security.tools.keytool * @bug 4419266 4842702 * @summary Make sure verifying signed Jar doesn't throw SecurityException + * @run junit VerifySignedJar */ import jdk.security.jarsigner.JarSigner; +import org.junit.jupiter.api.Test; import sun.security.tools.keytool.CertAndKeyGen; import sun.security.x509.X500Name; +import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; @@ -40,21 +42,24 @@ import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.Collections; -import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; -import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import static jdk.test.lib.Utils.runAndCheckException; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class VerifySignedJar { - public static void main(String[] args) throws Exception { - + @Test + void signedJarSecurityExceptionTest() throws Exception { Path j = createJar(); Path s = signJar(j, keyEntry("cn=duke")); @@ -70,38 +75,30 @@ public class VerifySignedJar { } // Read ZIP and JAR entries by name - Objects.requireNonNull(jf.getEntry("getprop.class")); - Objects.requireNonNull(jf.getJarEntry("getprop.class")); + assertNotNull(jf.getEntry("getprop.class")); + assertNotNull(jf.getJarEntry("getprop.class")); // Make sure we throw NPE on null parameters - runAndCheckException(() -> jf.getEntry(null), NullPointerException.class); - runAndCheckException(() -> jf.getJarEntry(null), NullPointerException.class); - runAndCheckException(() -> jf.getInputStream(null), NullPointerException.class); + assertThrows(NullPointerException.class, () -> jf.getEntry(null)); + assertThrows(NullPointerException.class, () -> jf.getJarEntry(null)); + assertThrows(NullPointerException.class, () -> jf.getInputStream(null)); } catch (SecurityException se) { - throw new Exception("Got SecurityException when verifying signed " + - "jar:" + se); + fail("Got SecurityException when verifying signed jar:" + se); } } // Check that a JAR entry is signed by an expected DN - private static void checkSignedBy(JarEntry e, String expectedDn) throws Exception { + private static void checkSignedBy(JarEntry e, String expectedDn) { Certificate[] certs = e.getCertificates(); - if (certs == null || certs.length == 0) { - throw new Exception("JarEntry has no certificates: " + e.getName()); - } - - if (certs[0] instanceof X509Certificate x) { - String name = x.getSubjectX500Principal().getName(); - if (!name.equalsIgnoreCase(expectedDn)) { - throw new Exception("Expected entry signed by %s, was %s".formatted(name, expectedDn)); - } - } else { - throw new Exception("Expected JarEntry.getCertificate to return X509Certificate"); - } + assertNotNull(certs, "JarEntry has no certificates: " + e.getName()); + assertNotEquals(0, certs.length, "JarEntry has no certificates: " + e.getName()); + var x = assertInstanceOf(X509Certificate.class, certs[0], "Expected JarEntry.getCertificate to return X509Certificate"); + String name = x.getSubjectX500Principal().getName(); + assertTrue(name.equalsIgnoreCase(expectedDn), "Expected entry signed by %s, was %s".formatted(name, expectedDn)); } - private static Path createJar() throws Exception { + private static Path createJar() throws IOException { Path j = Path.of("unsigned.jar"); try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(j))){ out.putNextEntry(new JarEntry("getprop.class")); diff --git a/test/jdk/java/util/jar/JarFile/jarVerification/MultiProviderTest.java b/test/jdk/java/util/jar/JarFile/jarVerification/MultiProviderTest.java index 4d191d7b3cd..b4b7fda081e 100644 --- a/test/jdk/java/util/jar/JarFile/jarVerification/MultiProviderTest.java +++ b/test/jdk/java/util/jar/JarFile/jarVerification/MultiProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,7 @@ * jdk.test.lib.JDKToolLauncher * MultiThreadLoad FooService * @modules java.base/jdk.internal.access:+open - * @run main MultiProviderTest - * @run main MultiProviderTest sign + * @run junit MultiProviderTest */ import java.io.File; @@ -51,27 +50,33 @@ import jdk.test.lib.compiler.CompilerUtils; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.util.JarUtils; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static java.util.Arrays.asList; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; public class MultiProviderTest { private static final String METAINFO = "META-INF/services/FooService"; - private static String COMBO_CP = Utils.TEST_CLASS_PATH + File.pathSeparator; private static String TEST_CLASS_PATH = System.getProperty("test.classes", "."); - private static boolean signJars = false; static final int NUM_JARS = 5; + // Reset per each test run under JUnit default lifecycle + private boolean signJars = false; + private String COMBO_CP = Utils.TEST_CLASS_PATH + File.pathSeparator; private static final String KEYSTORE = "keystore.jks"; private static final String ALIAS = "JavaTest"; private static final String STOREPASS = "changeit"; private static final String KEYPASS = "changeit"; - public static void main(String[] args) throws Throwable { - signJars = args.length >=1 && args[0].equals("sign"); + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void classLoadingTest(boolean sign) throws Throwable { + signJars = sign; initialize(); List cmds = new ArrayList<>(); cmds.add(JDKToolFinder.getJDKTool("java")); @@ -86,18 +91,16 @@ public class MultiProviderTest { "MultiThreadLoad", TEST_CLASS_PATH)); - try { + assertDoesNotThrow(() -> { OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(cmds.stream() - .filter(t -> !t.isEmpty()) - .toArray(String[]::new)) + .filter(t -> !t.isEmpty()) + .toArray(String[]::new)) .shouldHaveExitValue(0); System.out.println("Output:" + outputAnalyzer.getOutput()); - } catch (Throwable t) { - throw new RuntimeException("Unexpected fail.", t); - } + }); } - public static void initialize() throws Throwable { + public void initialize() throws Throwable { if (signJars) { genKey(); } diff --git a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java index e8abec354ed..1ba25ef6985 100644 --- a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java +++ b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * CreateMultiReleaseTestJars * jdk.test.lib.compiler.Compiler * jdk.test.lib.util.JarBuilder - * @run testng MultiReleaseJarAPI + * @run junit MultiReleaseJarAPI */ import java.io.File; @@ -44,37 +44,41 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; import java.util.jar.JarFile; +import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import jdk.test.lib.RandomFactory; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.*; public class MultiReleaseJarAPI { private static final Random RANDOM = RandomFactory.getRandom(); - String userdir = System.getProperty("user.dir","."); - CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); - File unversioned = new File(userdir, "unversioned.jar"); - File multirelease = new File(userdir, "multi-release.jar"); - File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + private static final String userdir = System.getProperty("user.dir", "."); + private static final CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + private static final File unversioned = new File(userdir, "unversioned.jar"); + private static final File multirelease = new File(userdir, "multi-release.jar"); + private static final File signedmultirelease = new File(userdir, "signed-multi-release.jar"); - - @BeforeClass - public void initialize() throws Exception { + @BeforeAll + public static void initialize() throws Exception { creator.compileEntries(); creator.buildUnversionedJar(); creator.buildMultiReleaseJar(); creator.buildSignedMultiReleaseJar(); } - @AfterClass - public void close() throws IOException { + @AfterAll + public static void close() throws IOException { Files.delete(unversioned.toPath()); Files.delete(multirelease.toPath()); Files.delete(signedmultirelease.toPath()); @@ -83,19 +87,19 @@ public class MultiReleaseJarAPI { @Test public void isMultiReleaseJar() throws Exception { try (JarFile jf = new JarFile(unversioned)) { - Assert.assertFalse(jf.isMultiRelease()); + assertFalse(jf.isMultiRelease()); } try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Runtime.version())) { - Assert.assertFalse(jf.isMultiRelease()); + assertFalse(jf.isMultiRelease()); } try (JarFile jf = new JarFile(multirelease)) { - Assert.assertTrue(jf.isMultiRelease()); + assertTrue(jf.isMultiRelease()); } try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Runtime.version())) { - Assert.assertTrue(jf.isMultiRelease()); + assertTrue(jf.isMultiRelease()); } testCustomMultiReleaseValue("true", true); @@ -155,45 +159,46 @@ public class MultiReleaseJarAPI { creator.buildCustomMultiReleaseJar(fileName, value, extraAttributes); File custom = new File(userdir, fileName); try (JarFile jf = new JarFile(custom, true, ZipFile.OPEN_READ, Runtime.version())) { - Assert.assertEquals(jf.isMultiRelease(), expected); + assertEquals(expected, jf.isMultiRelease()); } Files.delete(custom.toPath()); } - @DataProvider(name = "versions") - public Object[][] createVersionData() throws Exception { - return new Object[][]{ - {JarFile.baseVersion(), 8}, - {JarFile.runtimeVersion(), Runtime.version().major()}, - {Runtime.version(), Runtime.version().major()}, - {Runtime.Version.parse("7.1"), JarFile.baseVersion().major()}, - {Runtime.Version.parse("9"), 9}, - {Runtime.Version.parse("9.1.5-ea+200"), 9} - }; + public static Stream createVersionData() { + return Stream.of( + Arguments.of(JarFile.baseVersion(), 8), + Arguments.of(JarFile.runtimeVersion(), Runtime.version().major()), + Arguments.of(Runtime.version(), Runtime.version().major()), + Arguments.of(Runtime.Version.parse("7.1"), JarFile.baseVersion().major()), + Arguments.of(Runtime.Version.parse("9"), 9), + Arguments.of(Runtime.Version.parse("9.1.5-ea+200"), 9) + ); } - @Test(dataProvider="versions") + @ParameterizedTest + @MethodSource("createVersionData") public void testVersioning(Runtime.Version value, int xpected) throws Exception { Runtime.Version expected = Runtime.Version.parse(String.valueOf(xpected)); Runtime.Version base = JarFile.baseVersion(); // multi-release jar, opened as unversioned try (JarFile jar = new JarFile(multirelease)) { - Assert.assertEquals(jar.getVersion(), base); + assertEquals(base, jar.getVersion()); } System.err.println("test versioning for Release " + value); try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) { - Assert.assertEquals(jf.getVersion(), expected); + assertEquals(expected, jf.getVersion()); } // regular, unversioned, jar try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) { - Assert.assertEquals(jf.getVersion(), base); + assertEquals(base, jf.getVersion()); } } - @Test(dataProvider="versions") + @ParameterizedTest + @MethodSource("createVersionData") public void testAliasing(Runtime.Version version, int xpected) throws Exception { int n = Math.max(version.major(), JarFile.baseVersion().major()); Runtime.Version value = Runtime.Version.parse(String.valueOf(n)); @@ -231,7 +236,7 @@ public class MultiReleaseJarAPI { } assert versionedBytes.length > 0; - Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes)); + assertTrue(Arrays.equals(baseBytes, versionedBytes)); } @Test @@ -243,11 +248,11 @@ public class MultiReleaseJarAPI { try (JarFile jf = new JarFile(multirelease)) { ze1 = jf.getEntry(vname); } - Assert.assertEquals(ze1.getName(), vname); + assertEquals(vname, ze1.getName()); try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Runtime.Version.parse("9"))) { ze2 = jf.getEntry(rname); } - Assert.assertEquals(ze2.getName(), rname); - Assert.assertNotEquals(ze1.getName(), ze2.getName()); + assertEquals(rname, ze2.getName()); + assertNotEquals(ze2.getName(), ze1.getName()); } } diff --git a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java index 16f764c6674..7d3a933a619 100644 --- a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java +++ b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,17 +31,17 @@ * @build CreateMultiReleaseTestJars * jdk.test.lib.compiler.Compiler * jdk.test.lib.util.JarBuilder - * @run testng MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties - * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run junit MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run junit/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties */ import java.io.IOException; @@ -56,16 +56,19 @@ import java.util.concurrent.Executors; import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.SimpleFileServer; import jdk.test.lib.net.URIBuilder; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { private HttpServer server; private ExecutorService executor; static final String TESTCONTEXT = "/multi-release.jar"; //mapped to local file path - @BeforeClass + @BeforeAll public void initialize() throws Exception { server = SimpleFileServer.createFileServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), Path.of(System.getProperty("user.dir", ".")), SimpleFileServer.OutputLevel.INFO); @@ -86,7 +89,7 @@ public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { rootClass = cldr.loadClass("version.Main"); } - @AfterClass + @AfterAll public void close() throws IOException { // Windows requires server to stop before file is deleted if (server != null) { diff --git a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java index cbc9516542e..a742a593868 100644 --- a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java +++ b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,17 +29,17 @@ * @build CreateMultiReleaseTestJars * jdk.test.lib.compiler.Compiler * jdk.test.lib.util.JarBuilder - * @run testng MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties - * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run junit MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run junit/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties */ import java.io.File; @@ -54,12 +54,15 @@ import java.nio.file.Files; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import static org.junit.jupiter.api.Assertions.*; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class MultiReleaseJarProperties { final static int BASE_VERSION = JarFile.baseVersion().major(); @@ -70,7 +73,7 @@ public class MultiReleaseJarProperties { protected ClassLoader cldr; protected Class rootClass; - @BeforeClass + @BeforeAll public void initialize() throws Exception { CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); creator.compileEntries(); @@ -97,7 +100,7 @@ public class MultiReleaseJarProperties { rootClass = cldr.loadClass("version.Main"); } - @AfterClass + @AfterAll public void close() throws IOException { ((URLClassLoader) cldr).close(); Files.delete(multirelease.toPath()); @@ -115,7 +118,7 @@ public class MultiReleaseJarProperties { protected void invokeMethod(Class vcls, int expected) throws Throwable { MethodType mt = MethodType.methodType(int.class); MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt); - Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance())); + assertEquals(expected, (int) mh.invoke(vcls.newInstance())); } /* @@ -177,7 +180,7 @@ public class MultiReleaseJarProperties { resource = new String(bytes); } String match = "return " + rtVersion + ";"; - Assert.assertTrue(resource.contains(match)); + assertTrue(resource.contains(match)); } @Test @@ -194,6 +197,6 @@ public class MultiReleaseJarProperties { resource = new String(bytes); } String match = "return " + rtVersion + ";"; - Assert.assertTrue(resource.contains(match)); + assertTrue(resource.contains(match)); } } diff --git a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java index ec18cad0817..7e0bb2c1ca7 100644 --- a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java +++ b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * @build CreateMultiReleaseTestJars * jdk.test.lib.compiler.Compiler * jdk.test.lib.util.JarBuilder - * @run testng MultiReleaseJarSecurity + * @run junit MultiReleaseJarSecurity */ import java.io.File; @@ -38,45 +38,45 @@ import java.io.InputStream; import java.nio.file.Files; import java.security.CodeSigner; import java.security.cert.Certificate; -import java.util.Arrays; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipFile; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; public class MultiReleaseJarSecurity { static final int MAJOR_VERSION = Runtime.version().major(); - String userdir = System.getProperty("user.dir","."); - File multirelease = new File(userdir, "multi-release.jar"); - File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + static final String USER_DIR = System.getProperty("user.dir", "."); + static final File MULTI_RELEASE = new File(USER_DIR, "multi-release.jar"); + static final File SIGNED_MULTI_RELEASE = new File(USER_DIR, "signed-multi-release.jar"); - @BeforeClass - public void initialize() throws Exception { + @BeforeAll + public static void initialize() throws Exception { CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); creator.compileEntries(); creator.buildMultiReleaseJar(); creator.buildSignedMultiReleaseJar(); } - @AfterClass - public void close() throws IOException { - Files.delete(multirelease.toPath()); - Files.delete(signedmultirelease.toPath()); + @AfterAll + public static void close() throws IOException { + Files.delete(MULTI_RELEASE.toPath()); + Files.delete(SIGNED_MULTI_RELEASE.toPath()); } @Test public void testCertsAndSigners() throws IOException { - try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, Runtime.version())) { + try (JarFile jf = new JarFile(SIGNED_MULTI_RELEASE, true, ZipFile.OPEN_READ, Runtime.version())) { CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class")); CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + MAJOR_VERSION + "/version/Version.class")); - Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates())); - Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners())); + assertArrayEquals(rcas.getCertificates(), vcas.getCertificates()); + assertArrayEquals(rcas.getCodeSigners(), vcas.getCodeSigners()); } } diff --git a/test/jdk/java/util/jar/JarFile/mrjar/TestVersionedStream.java b/test/jdk/java/util/jar/JarFile/mrjar/TestVersionedStream.java index dbff39f814e..f88ab0821ae 100644 --- a/test/jdk/java/util/jar/JarFile/mrjar/TestVersionedStream.java +++ b/test/jdk/java/util/jar/JarFile/mrjar/TestVersionedStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * @library /test/lib * @build jdk.test.lib.Platform * jdk.test.lib.util.FileUtils - * @run testng TestVersionedStream + * @run junit TestVersionedStream */ import java.io.File; @@ -41,7 +41,6 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -54,18 +53,20 @@ import java.util.stream.Stream; import java.util.zip.ZipFile; import jdk.test.lib.util.FileUtils; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.*; public class TestVersionedStream { - private final Path userdir; - private final Set unversionedEntryNames; + private static final Path userdir; + private static final Set unversionedEntryNames; private static final int LATEST_VERSION = Runtime.version().feature(); - public TestVersionedStream() throws IOException { + static { userdir = Paths.get(System.getProperty("user.dir", ".")); // These are not real class files even though they end with .class. @@ -91,8 +92,7 @@ public class TestVersionedStream { "--release " + LATEST_VERSION + " -C v" + LATEST_VERSION + " ."); System.out.println("Contents of mmr.jar\n======="); - - try(JarFile jf = new JarFile("mmr.jar")) { + try (JarFile jf = new JarFile("mmr.jar")) { unversionedEntryNames = jf.stream() .map(je -> je.getName()) .peek(System.out::println) @@ -100,13 +100,14 @@ public class TestVersionedStream { ? nm.replaceFirst("META-INF/versions/\\d+/", "") : nm) .collect(Collectors.toCollection(LinkedHashSet::new)); + } catch (IOException e) { + throw new RuntimeException("Failed to init \"unversionedEntryNames\"", e); } - System.out.println("======="); } - @AfterClass - public void close() throws IOException { + @AfterAll + public static void close() throws IOException { Files.walk(userdir, 1) .filter(p -> !p.equals(userdir)) .forEach(p -> { @@ -122,53 +123,41 @@ public class TestVersionedStream { }); } - @DataProvider - public Object[][] data() { - return new Object[][] { - {Runtime.Version.parse("8")}, - {Runtime.Version.parse("9")}, - {Runtime.Version.parse("10")}, - {Runtime.Version.parse(Integer.toString(LATEST_VERSION))}, - {JarFile.baseVersion()}, - {JarFile.runtimeVersion()} - }; + public static Stream arguments() { + return Stream.of( + Runtime.Version.parse("8"), + Runtime.Version.parse("9"), + Runtime.Version.parse("10"), + Runtime.Version.parse(Integer.toString(LATEST_VERSION)), + JarFile.baseVersion(), + JarFile.runtimeVersion() + ); } - @Test(dataProvider="data") - public void test(Runtime.Version version) throws Exception { + @ParameterizedTest + @MethodSource("arguments") + public void versionTest(Runtime.Version version) throws Exception { try (JarFile jf = new JarFile(new File("mmr.jar"), false, ZipFile.OPEN_READ, version); Stream jes = jf.versionedStream()) { - Assert.assertNotNull(jes); + assertNotNull(jes); // put versioned entries in list so we can reuse them List versionedEntries = jes.collect(Collectors.toList()); - Assert.assertTrue(versionedEntries.size() > 0); + assertTrue(versionedEntries.size() > 0); // also keep the names - List versionedNames = new ArrayList<>(versionedEntries.size()); + List versionedNames = versionedEntries.stream() + .map(JarEntry::getName) + .collect(Collectors.toList()); // verify the correct order while building enames - Iterator allIt = unversionedEntryNames.iterator(); - Iterator verIt = versionedEntries.iterator(); - boolean match = false; + List unversionedOrder = new ArrayList<>(unversionedEntryNames); + unversionedOrder.retainAll(versionedNames); - while (verIt.hasNext()) { - match = false; - if (!allIt.hasNext()) break; - String name = verIt.next().getName(); - versionedNames.add(name); - while (allIt.hasNext()) { - if (name.equals(allIt.next())) { - match = true; - break; - } - } - } - if (!match) { - Assert.fail("versioned entries not in same order as unversioned entries"); - } + assertIterableEquals(unversionedOrder, versionedNames, + "versioned entries not in same order as unversioned entries"); // verify the contents: // value.[0] end of the path @@ -205,21 +194,21 @@ public class TestVersionedStream { expected.put("q/Bar.class", new String[] { "q/Bar.class", "META-INF/versions/10/q/Bar.class"}); } else { - Assert.fail("Test out of date, please add more cases"); + fail("Test out of date, please add more cases"); } } expected.entrySet().stream().forEach(e -> { String name = e.getKey(); int i = versionedNames.indexOf(name); - Assert.assertTrue(i != -1, name + " not in enames"); + assertTrue(i != -1, name + " not in enames"); JarEntry je = versionedEntries.get(i); try (InputStream is = jf.getInputStream(je)) { String s = new String(is.readAllBytes()).replaceAll(System.lineSeparator(), ""); // end of the path - Assert.assertTrue(s.endsWith(e.getValue()[0]), s); + assertTrue(s.endsWith(e.getValue()[0]), s); // getRealName() - Assert.assertTrue(je.getRealName().equals(e.getValue()[1])); + assertTrue(je.getRealName().equals(e.getValue()[1])); } catch (IOException x) { throw new UncheckedIOException(x); } @@ -227,12 +216,12 @@ public class TestVersionedStream { if (!unversionedEntryNames.contains("META-INF/Foo.class") || versionedNames.indexOf("META-INF/Foo.class") != -1) { - Assert.fail("versioned META-INF/Foo.class test failed"); + fail("versioned META-INF/Foo.class test failed"); } } } - private void createFiles(String... files) { + private static void createFiles(String... files) { ArrayList list = new ArrayList(); Arrays.stream(files) .map(f -> Paths.get(userdir.toAbsolutePath().toString(), f)) @@ -248,7 +237,7 @@ public class TestVersionedStream { }}); } - private void jar(String args) { + private static void jar(String args) { ToolProvider jar = ToolProvider.findFirst("jar").orElseThrow(); jar.run(System.out, System.err, args.split(" +")); } diff --git a/test/jdk/java/util/jar/JarInputStream/EmptyJar.java b/test/jdk/java/util/jar/JarInputStream/EmptyJar.java index 9762455460c..ff961844685 100644 --- a/test/jdk/java/util/jar/JarInputStream/EmptyJar.java +++ b/test/jdk/java/util/jar/JarInputStream/EmptyJar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,18 +26,22 @@ @summary Make sure JarInputStream constructor will not throw NullPointerException when the JAR file is empty. - */ + @run junit EmptyJar + */ + +import org.junit.jupiter.api.Test; import java.util.jar.*; import java.io.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + public class EmptyJar { - public static void main(String args[]) throws Exception { - try { - JarInputStream is = new JarInputStream - (new ByteArrayInputStream(new byte[0])); - } catch (NullPointerException e) { - throw new Exception("unexpected NullPointerException"); - } + + @Test + void npeTest() { + // Ensure no NPE is thrown + assertDoesNotThrow(() -> new JarInputStream(new ByteArrayInputStream(new byte[0])), + "unexpected NullPointerException"); } } diff --git a/test/jdk/java/util/jar/JarInputStream/ExtraFileInMetaInf.java b/test/jdk/java/util/jar/JarInputStream/ExtraFileInMetaInf.java index 45865ec0b8f..fe88d225444 100644 --- a/test/jdk/java/util/jar/JarInputStream/ExtraFileInMetaInf.java +++ b/test/jdk/java/util/jar/JarInputStream/ExtraFileInMetaInf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,16 +27,24 @@ * @summary JarInputStream doesn't provide certificates for some file under META-INF * @modules java.base/sun.security.tools.keytool * jdk.jartool/sun.security.tools.jarsigner + * @run junit ExtraFileInMetaInf */ +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + import java.util.jar.*; import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -public class ExtraFileInMetaInf { - public static void main(String args[]) throws Exception { +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; +public class ExtraFileInMetaInf { + + @BeforeAll + static void setup() throws Exception { // Create a zip file with 2 entries try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("x.jar"))) { @@ -44,7 +52,6 @@ public class ExtraFileInMetaInf { zos.write(new byte[10]); zos.putNextEntry(new ZipEntry("x")); zos.write(new byte[10]); - zos.close(); } // Sign it @@ -54,7 +61,10 @@ public class ExtraFileInMetaInf { "-keyalg rsa -alias a -dname CN=A -genkeypair").split(" ")); sun.security.tools.jarsigner.Main.main( "-keystore ks -storepass changeit x.jar a".split(" ")); + } + @Test + void checkSignedTest() throws IOException { // Check if the entries are signed try (JarInputStream jis = new JarInputStream(new FileInputStream("x.jar"))) { @@ -63,9 +73,7 @@ public class ExtraFileInMetaInf { String name = je.toString(); if (name.equals("META-INF/SUB/file") || name.equals("x")) { while (jis.read(new byte[1000]) >= 0); - if (je.getCertificates() == null) { - throw new Exception(name + " not signed"); - } + assertNotNull(je.getCertificates(), name + " not signed"); } } } diff --git a/test/jdk/java/util/jar/JarInputStream/ScanSignedJar.java b/test/jdk/java/util/jar/JarInputStream/ScanSignedJar.java index 86dbf793e74..23e0a81c4cf 100644 --- a/test/jdk/java/util/jar/JarInputStream/ScanSignedJar.java +++ b/test/jdk/java/util/jar/JarInputStream/ScanSignedJar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,19 @@ * @test * @bug 6284489 * @summary Confirm that JarEntry.getCertificates identifies signed entries. + * @run junit ScanSignedJar */ +import org.junit.jupiter.api.Test; + +import java.io.IOException; import java.net.URL; import java.security.CodeSigner; import java.security.cert.Certificate; import java.util.jar.*; +import static org.junit.jupiter.api.Assertions.fail; + /* * Confirm that the signed entries in a JAR file are identified correctly * when JarEntry.getCertificates is used to extract the signer's certificates. @@ -43,13 +49,13 @@ import java.util.jar.*; public class ScanSignedJar { private static final String JAR_LOCATION = - "file:" + - System.getProperty("test.src", ".") + - System.getProperty("file.separator") + - "signed.jar"; - - public static void main(String[] args) throws Exception { + "file:" + + System.getProperty("test.src", ".") + + System.getProperty("file.separator") + + "signed.jar"; + @Test + void signedJarTest() throws IOException { System.out.println("Opening " + JAR_LOCATION + "..."); JarInputStream inStream = new JarInputStream(new URL(JAR_LOCATION).openStream(), true); @@ -71,7 +77,7 @@ public class ScanSignedJar { System.out.println("[unsigned]\t" + name + "\t(" + size + " bytes)"); if (name.equals("Count.class")) { - throw new Exception("Count.class should be signed"); + fail("Count.class should be signed"); } } else if (signers != null && certificates != null) { System.out.println("[" + signers.length + @@ -80,7 +86,7 @@ public class ScanSignedJar { } else { System.out.println("[*ERROR*]\t" + name + "\t(" + size + " bytes)"); - throw new Exception("Cannot determine whether the entry is " + + fail("Cannot determine whether the entry is " + "signed or unsigned (signers[] doesn't match certs[])."); } } diff --git a/test/jdk/java/util/jar/JarInputStream/TestIndexedJarWithBadSignature.java b/test/jdk/java/util/jar/JarInputStream/TestIndexedJarWithBadSignature.java index 2e74eb10069..47dc572aa6b 100644 --- a/test/jdk/java/util/jar/JarInputStream/TestIndexedJarWithBadSignature.java +++ b/test/jdk/java/util/jar/JarInputStream/TestIndexedJarWithBadSignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,32 +26,32 @@ * @bug 6544278 * @summary Confirm the JarInputStream throws the SecurityException when * verifying an indexed jar file with corrupted signature + * @run junit TestIndexedJarWithBadSignature */ +import org.junit.jupiter.api.Test; + import java.io.IOException; import java.io.FileInputStream; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; +import static org.junit.jupiter.api.Assertions.assertThrows; + public class TestIndexedJarWithBadSignature { - public static void main(String...args) throws Throwable { + @Test + void securityExceptionTest() throws IOException { try (JarInputStream jis = new JarInputStream( - new FileInputStream(System.getProperty("test.src", ".") + - System.getProperty("file.separator") + - "BadSignedJar.jar"))) - { - JarEntry je1 = jis.getNextJarEntry(); - while(je1!=null){ - System.out.println("Jar Entry1==>"+je1.getName()); - je1 = jis.getNextJarEntry(); // This should throw Security Exception - } - throw new RuntimeException( - "Test Failed:Security Exception not being thrown"); - } catch (IOException ie){ - ie.printStackTrace(); - } catch (SecurityException e) { - System.out.println("Test passed: Security Exception thrown as expected"); + new FileInputStream(System.getProperty("test.src", ".") + + System.getProperty("file.separator") + + "BadSignedJar.jar"))) { + assertThrows(SecurityException.class, () -> { + JarEntry je1; + while ((je1 = jis.getNextJarEntry()) != null) { + System.out.println("Jar Entry1==>" + je1.getName()); + } + }); } } } diff --git a/test/jdk/java/util/jar/Manifest/CreateManifest.java b/test/jdk/java/util/jar/Manifest/CreateManifest.java index 6655089b56d..2eee24fb0be 100644 --- a/test/jdk/java/util/jar/Manifest/CreateManifest.java +++ b/test/jdk/java/util/jar/Manifest/CreateManifest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,40 +27,43 @@ * @summary Jar tools fails to generate manifest correctly when boundary condition hit * @modules jdk.jartool/sun.tools.jar * @compile -XDignore.symbol.file=true CreateManifest.java - * @run main CreateManifest + * @run junit CreateManifest */ +import org.junit.jupiter.api.Test; + +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.jar.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class CreateManifest { -public static void main(String arg[]) throws Exception { + @Test + void boundaryTest() throws IOException { + String jarFileName = "test.jar"; + String ManifestName = "MANIFEST.MF"; - String jarFileName = "test.jar"; - String ManifestName = "MANIFEST.MF"; + // create the MANIFEST.MF file + Files.write(Paths.get(ManifestName), FILE_CONTENTS.getBytes()); - // create the MANIFEST.MF file - Files.write(Paths.get(ManifestName), FILE_CONTENTS.getBytes()); + String [] args = new String [] { "cvfm", jarFileName, ManifestName}; + sun.tools.jar.Main jartool = + new sun.tools.jar.Main(System.out, System.err, "jar"); + jartool.run(args); - String [] args = new String [] { "cvfm", jarFileName, ManifestName}; - sun.tools.jar.Main jartool = - new sun.tools.jar.Main(System.out, System.err, "jar"); - jartool.run(args); - - try (JarFile jf = new JarFile(jarFileName)) { - Manifest m = jf.getManifest(); - String result = m.getMainAttributes().getValue("Class-path"); - if (result == null) - throw new RuntimeException("Failed to add Class-path attribute to manifest"); - } finally { - Files.deleteIfExists(Paths.get(jarFileName)); - Files.deleteIfExists(Paths.get(ManifestName)); + try (JarFile jf = new JarFile(jarFileName)) { + Manifest m = jf.getManifest(); + String result = m.getMainAttributes().getValue("Class-path"); + assertNotNull(result, "Failed to add Class-path attribute to manifest"); + } finally { + Files.deleteIfExists(Paths.get(jarFileName)); + Files.deleteIfExists(Paths.get(ManifestName)); + } } -} - private static final String FILE_CONTENTS = "Class-path: \n" + " /ade/dtsao_re/oracle/emcore//lib/em-core-testconsole-uimodel.jar \n" + diff --git a/test/jdk/java/util/jar/Manifest/IncludeInExceptionsTest.java b/test/jdk/java/util/jar/Manifest/IncludeInExceptionsTest.java index 1e272015087..bb3cd6e23ef 100644 --- a/test/jdk/java/util/jar/Manifest/IncludeInExceptionsTest.java +++ b/test/jdk/java/util/jar/Manifest/IncludeInExceptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,7 +21,9 @@ * questions. */ -import java.io.File; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; @@ -30,23 +32,29 @@ import java.util.concurrent.Callable; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; +import java.util.stream.Stream; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; -/** +/* * @test * @bug 8216362 - * @run main/othervm -Djdk.includeInExceptions=jar IncludeInExceptionsTest yes - * @run main/othervm IncludeInExceptionsTest - * @summary Verify that the property jdk.net.includeInExceptions works as expected + * @run junit/othervm -Djdk.includeInExceptions=jar IncludeInExceptionsTest + * @run junit/othervm IncludeInExceptionsTest + * @summary Verify that the property jdk.includeInExceptions works as expected * when an error occurs while reading an invalid Manifest file. */ + /* * @see Manifest#Manifest(JarVerifier,InputStream,String) * @see Manifest#getErrorPosition */ public class IncludeInExceptionsTest { + private static final boolean includeInExceptions = System.getProperty("jdk.includeInExceptions") != null; + static final String FILENAME = "Unique-Filename-Expected-In_Msg.jar"; static final byte[] INVALID_MANIFEST = ( @@ -66,36 +74,26 @@ public class IncludeInExceptionsTest { return jar; } - static void test(Callable attempt, boolean includeInExceptions) throws Exception { - try { - attempt.call(); - throw new AssertionError("Excpected Exception not thrown"); - } catch (IOException e) { - boolean foundFileName = e.getMessage().contains(FILENAME); - if(includeInExceptions && !foundFileName) { - throw new AssertionError("JAR file name expected but not found in error message"); - } else if (foundFileName && !includeInExceptions) { - throw new AssertionError("JAR file name found but should not be in error message"); - } + @ParameterizedTest + @MethodSource("manifests") + void testInvalidManifest(Callable attempt) { + var ioException = assertThrows(IOException.class, attempt::call); + boolean foundFileName = ioException.getMessage().contains(FILENAME); + if (includeInExceptions && !foundFileName) { + fail("JAR file name expected but not found in error message"); + } else if (foundFileName && !includeInExceptions) { + fail("JAR file name found but should not be in error message"); } } - public static void main(String[] args) throws Exception { - - boolean includeInExceptions; - if(args.length > 0) { - includeInExceptions = true; - System.out.println("**** Running test WITH -Djdk.includeInExceptions=jar"); - } else { - includeInExceptions = false; - System.out.println("**** Running test WITHOUT -Djdk.includeInExceptions=jar"); - } - - test(() -> new JarFile(createJarInvalidManifest(FILENAME)).getManifest(), - includeInExceptions); - test(() -> new JarFile(createJarInvalidManifest("Verifying-" + FILENAME), - true).getManifest(), includeInExceptions); + static Stream> manifests() { + Callable jarName = () -> new JarFile(createJarInvalidManifest(FILENAME)).getManifest(); + Callable jarNameVerify = () -> new JarFile(createJarInvalidManifest("Verifying-" + FILENAME), + true).getManifest(); + return Stream.of( + jarName, + jarNameVerify + ); } - } diff --git a/test/jdk/java/util/jar/Manifest/LineBreakLineWidth.java b/test/jdk/java/util/jar/Manifest/LineBreakLineWidth.java index 8009db75601..f33bd7a276f 100644 --- a/test/jdk/java/util/jar/Manifest/LineBreakLineWidth.java +++ b/test/jdk/java/util/jar/Manifest/LineBreakLineWidth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,23 +21,22 @@ * questions. */ -import static java.nio.charset.StandardCharsets.UTF_8; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.util.jar.Manifest; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.*; /** * @test * @bug 6372077 - * @run testng LineBreakLineWidth + * @run junit LineBreakLineWidth * @summary write valid manifests with respect to line breaks * and read any line width */ @@ -99,16 +98,10 @@ public class LineBreakLineWidth { assertMainAndSectionValues(mf, name, value); } - static void writeInvalidManifestThrowsException(String name, String value) - throws IOException { - try { - writeManifest(name, value); - } catch (IllegalArgumentException e) { - // no invalid manifest was produced which is considered acceptable - return; - } - - fail("no error writing manifest considered invalid"); + static void writeInvalidManifestThrowsException(String name, String value) { + // no invalid manifest was produced which is considered acceptable + assertThrows(IllegalArgumentException.class, + () -> writeManifest(name, value), "no error writing manifest considered invalid"); } /** @@ -278,8 +271,8 @@ public class LineBreakLineWidth { String mainValue = mf.getMainAttributes().getValue(name); String sectionValue = mf.getAttributes(name).getValue(name); - assertEquals(value, mainValue, "value different in main section"); - assertEquals(value, sectionValue, "value different in named section"); + assertEquals(mainValue, value, "value different in main section"); + assertEquals(sectionValue, value, "value different in named section"); } } diff --git a/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java b/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java index 28921bba868..cad0048f098 100644 --- a/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java +++ b/test/jdk/java/util/jar/Manifest/ValueUtf8Coding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,8 +21,6 @@ * questions. */ -import static java.nio.charset.StandardCharsets.UTF_8; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -32,13 +30,15 @@ import java.util.jar.Manifest; import java.util.List; import java.util.ArrayList; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.*; /** * @test * @bug 8066619 8351567 - * @run testng ValueUtf8Coding + * @run junit ValueUtf8Coding * @summary Tests encoding and decoding manifest header values to and from * UTF-8 with the complete Unicode character set. */ /* @@ -187,11 +187,11 @@ public class ValueUtf8Coding { String value = values.get(i); Name name = azName(i); - assertEquals(mf.getMainAttributes().getValue(name), value, + assertEquals(value, mf.getMainAttributes().getValue(name), "main attributes header value"); Attributes attributes = mf.getAttributes(value); assertNotNull(attributes, "named section"); - assertEquals(attributes.getValue(name), value, + assertEquals(value, attributes.getValue(name), "named section attributes value"); } } diff --git a/test/jdk/java/util/jar/Manifest/WriteBinaryStructure.java b/test/jdk/java/util/jar/Manifest/WriteBinaryStructure.java index 379de6b1adb..f91b518aa6c 100644 --- a/test/jdk/java/util/jar/Manifest/WriteBinaryStructure.java +++ b/test/jdk/java/util/jar/Manifest/WriteBinaryStructure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,22 +21,22 @@ * questions. */ -import static java.nio.charset.StandardCharsets.UTF_8; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; import java.util.jar.Manifest; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; -/** +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.*; + +/* * @test * @bug 8066619 - * @run testng WriteBinaryStructure * @summary Tests that jar manifests are written in a particular structure + * @run junit WriteBinaryStructure */ public class WriteBinaryStructure { @@ -47,10 +47,11 @@ public class WriteBinaryStructure { mf.getMainAttributes().put(new Name("Key"), "Value"); ByteArrayOutputStream buf = new ByteArrayOutputStream(); mf.write(buf); - assertEquals(buf.toByteArray(), ( + assertArrayEquals(( "Manifest-Version: 1.0\r\n" + "Key: Value\r\n" + - "\r\n").getBytes(UTF_8)); + "\r\n").getBytes(UTF_8), + buf.toByteArray()); } @Test @@ -62,12 +63,12 @@ public class WriteBinaryStructure { attributes.put(new Name("Key"), "Value"); ByteArrayOutputStream buf = new ByteArrayOutputStream(); mf.write(buf); - assertEquals(buf.toByteArray(), ( + assertArrayEquals(( "Manifest-Version: 1.0\r\n" + "\r\n" + "Name: Individual-Section-Name\r\n" + "Key: Value\r\n" + - "\r\n").getBytes(UTF_8)); + "\r\n").getBytes(UTF_8), + buf.toByteArray()); } - } diff --git a/test/jdk/java/util/jar/TestExtra.java b/test/jdk/java/util/jar/TestExtra.java index fa6408ba570..776b5e67d14 100644 --- a/test/jdk/java/util/jar/TestExtra.java +++ b/test/jdk/java/util/jar/TestExtra.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2026, Oracle and/or its affiliates. All rights reserved. * 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,180 +21,84 @@ * questions. */ -/** +/* * @test * @bug 6480504 6303183 * @summary Test that client-provided data in the extra field is written and * read correctly, taking into account the JAR_MAGIC written into the extra - * field of the first entry of JAR files. - * @author Dave Bristor + * field of the first entry of JAR files. ZIP file specific. + * @run junit TestExtra */ +import org.junit.jupiter.api.Test; + import java.io.*; import java.nio.charset.Charset; -import java.util.Arrays; +import java.nio.charset.StandardCharsets; import java.util.jar.*; import java.util.zip.*; -/** - * Tests that the get/set operations on extra data in zip and jar files work - * as advertised. The base class tests ZIP files, the member class - * TestJarExtra checks JAR files. - */ -public class TestExtra { - static final int JAR_MAGIC = 0xcafe; // private IN JarOutputStream.java - static final int TEST_HEADER = 0xbabe; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; - static final Charset ascii = Charset.forName("ASCII"); +// Tests that the get/set operations on extra data in ZIP files work as advertised. +public class TestExtra { + + static final int TEST_HEADER = 0xbabe; + static final Charset ascii = StandardCharsets.US_ASCII; // ZipEntry extra data static final byte[][] extra = new byte[][] { - ascii.encode("hello, world").array(), - ascii.encode("foo bar").array() + ascii.encode("hello, world").array(), + ascii.encode("foo bar").array() }; - // For naming entries in JAR/ZIP streams - int count = 1; + // For naming entries in ZIP streams + static int count = 1; // Use byte arrays instead of files - ByteArrayOutputStream baos; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); - // JAR/ZIP content written here. - ZipOutputStream zos; + // ZIP content written here. + ZipOutputStream zos = assertDoesNotThrow(() -> getOutputStream(baos)); - public static void realMain(String[] args) throws Throwable{ - new TestExtra().testHeaderPlusData(); - - new TestJarExtra().testHeaderPlusData(); - new TestJarExtra().testHeaderOnly(); - new TestJarExtra().testClientJarMagic(); - } - - TestExtra() { - try { - baos = new ByteArrayOutputStream(); - zos = getOutputStream(baos); - } catch (Throwable t) { - unexpected(t); - } - } - - /** Test that a header + data set by client works. */ + // Test that a header + data set by client works. + @Test void testHeaderPlusData() throws IOException { for (byte[] b : extra) { ZipEntry ze = getEntry(); byte[] data = new byte[b.length + 4]; set16(data, 0, TEST_HEADER); set16(data, 2, b.length); - for (int i = 0; i < b.length; i++) { - data[i + 4] = b[i]; - } + System.arraycopy(b, 0, data, 4, b.length); ze.setExtra(data); zos.putNextEntry(ze); } zos.close(); - ZipInputStream zis = getInputStream(); - ZipEntry ze = zis.getNextEntry(); checkEntry(ze, 0, extra[0].length); - ze = zis.getNextEntry(); checkEntry(ze, 1, extra[1].length); } - /** Test that a header only (i.e., no extra "data") set by client works. */ - void testHeaderOnly() throws IOException { - ZipEntry ze = getEntry(); - byte[] data = new byte[4]; - set16(data, 0, TEST_HEADER); - set16(data, 2, 0); // Length of data is 0. - ze.setExtra(data); - zos.putNextEntry(ze); - - zos.close(); - - ZipInputStream zis = getInputStream(); - - ze = zis.getNextEntry(); - checkExtra(data, ze.getExtra()); - checkEntry(ze, 0, 0); - } - - /** Tests the client providing extra data which uses JAR_MAGIC header. */ - void testClientJarMagic() throws IOException { - ZipEntry ze = getEntry(); - byte[] data = new byte[8]; - - set16(data, 0, TEST_HEADER); - set16(data, 2, 0); // Length of data is 0. - set16(data, 4, JAR_MAGIC); - set16(data, 6, 0); // Length of data is 0. - - ze.setExtra(data); - zos.putNextEntry(ze); - - zos.close(); - - ZipInputStream zis = getInputStream(); - ze = zis.getNextEntry(); - byte[] e = ze.getExtra(); - checkExtra(data, ze.getExtra()); - checkEntry(ze, 0, 0); - } - - // check if all "expected" extra fields equal to their - // corresponding fields in "extra". The "extra" might have - // timestamp fields added by ZOS. - static void checkExtra(byte[] expected, byte[] extra) { - if (expected == null) - return; - int off = 0; - int len = expected.length; - while (off + 4 < len) { - int tag = get16(expected, off); - int sz = get16(expected, off + 2); - int off0 = 0; - int len0 = extra.length; - boolean matched = false; - while (off0 + 4 < len0) { - int tag0 = get16(extra, off0); - int sz0 = get16(extra, off0 + 2); - if (tag == tag0 && sz == sz0) { - matched = true; - for (int i = 0; i < sz; i++) { - if (expected[off + i] != extra[off0 +i]) - matched = false; - } - break; - } - off0 += (4 + sz0); - } - if (!matched) { - fail("Expected extra data [tag=" + tag + "sz=" + sz + "] check failed"); - } - off += (4 + sz); - } - } - - /** Check that the entry's extra data is correct. */ + // Check that the entry's extra data is correct. void checkEntry(ZipEntry ze, int count, int dataLength) { byte[] extraData = ze.getExtra(); byte[] data = getField(TEST_HEADER, extraData); - if (!check(data != null, "unexpected null data for TEST_HEADER")) { - return; - } - + assertNotNull(data, "unexpected null data for TEST_HEADER"); if (dataLength == 0) { - check(data.length == 0, "unexpected non-zero data length for TEST_HEADER"); + assertEquals(0, data.length, "unexpected non-zero data length for TEST_HEADER"); } else { - check(Arrays.equals(extra[count], data), - "failed to get entry " + ze.getName() - + ", expected " + new String(extra[count]) + ", got '" + new String(data) + "'"); + assertArrayEquals(data, extra[count], + "failed to get entry " + ze.getName() + + ", expected " + new String(extra[count]) + ", got '" + new String(data) + "'"); } } - /** Look up descriptor in data, returning corresponding byte[]. */ + // Look up descriptor in data, returning corresponding byte[]. static byte[] getField(int descriptor, byte[] data) { byte[] rc = null; try { @@ -218,69 +122,23 @@ public class TestExtra { ZipInputStream getInputStream() { return new ZipInputStream( - new ByteArrayInputStream(baos.toByteArray())); + new ByteArrayInputStream(baos.toByteArray())); } - ZipOutputStream getOutputStream(ByteArrayOutputStream baos) throws IOException { + ZipOutputStream getOutputStream(ByteArrayOutputStream baos) { return new ZipOutputStream(baos); } - ZipInputStream getInputStream(ByteArrayInputStream bais) throws IOException { - return new ZipInputStream(bais); + ZipEntry getEntry() { + return new ZipEntry("zip" + count++ + ".txt"); } - ZipEntry getEntry() { return new ZipEntry("zip" + count++ + ".txt"); } - - - private static int get16(byte[] b, int off) { - return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8); + static int get16(byte[] b, int off) { + return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8); } - private static void set16(byte[] b, int off, int value) { - b[off+0] = (byte)value; - b[off+1] = (byte)(value >> 8); + static void set16(byte[] b, int off, int value) { + b[off + 0] = (byte) value; + b[off + 1] = (byte) (value >> 8); } - - /** Test extra field of a JAR file. */ - static class TestJarExtra extends TestExtra { - ZipOutputStream getOutputStream(ByteArrayOutputStream baos) throws IOException { - return new JarOutputStream(baos); - } - - ZipInputStream getInputStream(ByteArrayInputStream bais) throws IOException { - return new JarInputStream(bais); - } - - ZipEntry getEntry() { return new ZipEntry("jar" + count++ + ".txt"); } - - void checkEntry(ZipEntry ze, int count, int dataLength) { - // zeroth entry should have JAR_MAGIC - if (count == 0) { - byte[] extraData = ze.getExtra(); - byte[] data = getField(JAR_MAGIC, extraData); - if (!check(data != null, "unexpected null data for JAR_MAGIC")) { - check(data.length != 0, "unexpected non-zero data length for JAR_MAGIC"); - } - } - // In a jar file, the first ZipEntry should have both JAR_MAGIC - // and the TEST_HEADER, so check that also. - super.checkEntry(ze, count, dataLength); - } - } - - //--------------------- Infrastructure --------------------------- - static volatile int passed = 0, failed = 0; - static void pass() {passed++;} - static void fail() {failed++; Thread.dumpStack();} - static void fail(String msg) {System.out.println(msg); fail();} - static void unexpected(Throwable t) {failed++; t.printStackTrace();} - static void check(boolean cond) {if (cond) pass(); else fail();} - static boolean check(boolean cond, String msg) {if (cond) pass(); else fail(msg); return cond; } - static void equal(Object x, Object y) { - if (x == null ? y == null : x.equals(y)) pass(); - else fail(x + " not equal to " + y);} - public static void main(String[] args) throws Throwable { - try {realMain(args);} catch (Throwable t) {unexpected(t);} - System.out.println("\nPassed = " + passed + " failed = " + failed); - if (failed > 0) throw new Error("Some tests failed");} } diff --git a/test/jdk/java/util/jar/TestJarExtra.java b/test/jdk/java/util/jar/TestJarExtra.java new file mode 100644 index 00000000000..6619727bfe8 --- /dev/null +++ b/test/jdk/java/util/jar/TestJarExtra.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6480504 6303183 + * @summary Test that client-provided data in the extra field is written and + * read correctly, taking into account the JAR_MAGIC written into the extra + * field of the first entry of JAR files. Jar file specific. + * @run junit TestJarExtra + */ + +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; + +// Tests that the get/set operations on extra data in JAR files work as advertised. +public class TestJarExtra { + + static final int JAR_MAGIC = 0xcafe; // private IN JarOutputStream.java + static final int TEST_HEADER = 0xbabe; + // For naming entries in JAR streams + static int count = 1; + static final Charset ascii = StandardCharsets.US_ASCII; + // ZipEntry extra data + static final byte[][] extra = new byte[][] { + ascii.encode("hello, world").array(), + ascii.encode("foo bar").array() + }; + + // Use byte arrays instead of files + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // JAR content written here. + JarOutputStream jos = assertDoesNotThrow(() -> getOutputStream(baos)); + + // Test that a header + data set by client works. + @Test + void testHeaderPlusData() throws IOException { + for (byte[] b : extra) { + ZipEntry ze = getEntry(); + byte[] data = new byte[b.length + 4]; + set16(data, 0, TEST_HEADER); + set16(data, 2, b.length); + System.arraycopy(b, 0, data, 4, b.length); + ze.setExtra(data); + jos.putNextEntry(ze); + } + jos.close(); + ZipInputStream zis = getInputStream(); + ZipEntry ze = zis.getNextEntry(); + checkEntry(ze, 0, extra[0].length); + ze = zis.getNextEntry(); + checkEntry(ze, 1, extra[1].length); + } + + // Test that a header only (i.e., no extra "data") set by client works. + @Test + void testHeaderOnly() throws IOException { + ZipEntry ze = getEntry(); + byte[] data = new byte[4]; + set16(data, 0, TEST_HEADER); + set16(data, 2, 0); // Length of data is 0. + ze.setExtra(data); + jos.putNextEntry(ze); + jos.close(); + ZipInputStream zis = getInputStream(); + ze = zis.getNextEntry(); + checkExtra(data, ze.getExtra()); + checkEntry(ze, 0, 0); + } + + // Tests the client providing extra data which uses JAR_MAGIC header. + @Test + void testClientJarMagic() throws IOException { + ZipEntry ze = getEntry(); + byte[] data = new byte[8]; + set16(data, 0, TEST_HEADER); + set16(data, 2, 0); // Length of data is 0. + set16(data, 4, JAR_MAGIC); + set16(data, 6, 0); // Length of data is 0. + ze.setExtra(data); + jos.putNextEntry(ze); + jos.close(); + ZipInputStream zis = getInputStream(); + ze = zis.getNextEntry(); + byte[] e = ze.getExtra(); + checkExtra(data, ze.getExtra()); + checkEntry(ze, 0, 0); + } + + JarOutputStream getOutputStream(ByteArrayOutputStream baos) throws IOException { + return new JarOutputStream(baos); + } + + ZipInputStream getInputStream() { + return new ZipInputStream( + new ByteArrayInputStream(baos.toByteArray())); + } + + ZipEntry getEntry() { + return new ZipEntry("jar" + count++ + ".txt"); + } + + // check if all "expected" extra fields equal to their + // corresponding fields in "extra". The "extra" might have + // timestamp fields added by ZOS. + static void checkExtra(byte[] expected, byte[] extra) { + if (expected == null) + return; + int off = 0; + int len = expected.length; + while (off + 4 < len) { + int tag = get16(expected, off); + int sz = get16(expected, off + 2); + int off0 = 0; + int len0 = extra.length; + boolean matched = false; + while (off0 + 4 < len0) { + int tag0 = get16(extra, off0); + int sz0 = get16(extra, off0 + 2); + if (tag == tag0 && sz == sz0) { + matched = true; + for (int i = 0; i < sz; i++) { + if (expected[off + i] != extra[off0 + i]) + matched = false; + } + break; + } + off0 += (4 + sz0); + } + if (!matched) { + fail("Expected extra data [tag=" + tag + "sz=" + sz + "] check failed"); + } + off += (4 + sz); + } + } + + void checkEntry(ZipEntry ze, int count, int dataLength) { + // zeroth entry should have JAR_MAGIC + if (count == 0) { + byte[] extraData = ze.getExtra(); + byte[] data = getField(JAR_MAGIC, extraData); + assertNotNull(data, "unexpected null data for JAR_MAGIC"); + assertEquals(0, data.length, "unexpected non-zero data length for JAR_MAGIC"); + } + // In a JAR file, the first ZipEntry should have both JAR_MAGIC + // and the TEST_HEADER, so check that also. + byte[] extraData = ze.getExtra(); + byte[] data = getField(TEST_HEADER, extraData); + assertNotNull(data, "unexpected null data for TEST_HEADER"); + if (dataLength == 0) { + assertEquals(0, data.length, "unexpected non-zero data length for TEST_HEADER"); + } else { + assertArrayEquals(data, extra[count], + "failed to get entry " + ze.getName() + + ", expected " + new String(extra[count]) + ", got '" + new String(data) + "'"); + } + } + + // Look up descriptor in data, returning corresponding byte[]. + static byte[] getField(int descriptor, byte[] data) { + byte[] rc = null; + try { + int i = 0; + while (i < data.length) { + if (get16(data, i) == descriptor) { + int length = get16(data, i + 2); + rc = new byte[length]; + for (int j = 0; j < length; j++) { + rc[j] = data[i + 4 + j]; + } + return rc; + } + i += get16(data, i + 2) + 4; + } + } catch (ArrayIndexOutOfBoundsException e) { + // descriptor not found + } + return rc; + } + + static int get16(byte[] b, int off) { + return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8); + } + + static void set16(byte[] b, int off, int value) { + b[off + 0] = (byte) value; + b[off + 1] = (byte) (value >> 8); + } +} From 63c1cb3ad1cc3be22fd8b401894acf37683dad67 Mon Sep 17 00:00:00 2001 From: Frederic Thevenet Date: Mon, 2 Mar 2026 18:30:29 +0000 Subject: [PATCH 016/170] 8378702: jdk.test.lib.Platform.isMusl() may return false negative on Alpine Linux Reviewed-by: stuefe, rriggs --- test/lib/jdk/test/lib/Platform.java | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 75fdef048bc..170e53930d8 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.nio.file.Paths; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Stream; import static java.util.Locale.ROOT; public class Platform { @@ -188,14 +189,17 @@ public class Platform { } public static boolean isMusl() { - try { - ProcessBuilder pb = new ProcessBuilder("ldd", "--version"); + var lddPath = Stream.of("/bin/ldd", "/usr/bin/ldd").filter(p -> Files.exists(Path.of(p))).findFirst(); + if (lddPath.isPresent()) { + ProcessBuilder pb = new ProcessBuilder(lddPath.get(), "--version"); pb.redirectErrorStream(true); - Process p = pb.start(); - BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream())); - String l = b.readLine(); - if (l != null && l.contains("musl")) { return true; } - } catch(Exception e) { + try (Process p = pb.start()) { + BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream())); + String l = b.readLine(); + return (l != null && l.contains("musl")); + } catch (Exception e) { + e.printStackTrace(); + } } return false; } From 8009a714ba81af8b6a7b422f510ae5d6509a73a7 Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Tue, 3 Mar 2026 03:25:23 +0000 Subject: [PATCH 017/170] 8378810: Enable missing FFM test via jtreg requires for RISC-V Reviewed-by: fyang --- .../jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java index 2877e8a4a85..ff853d174b1 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -27,7 +27,8 @@ * @summary guarantee(loc != NULL) failed: missing saved register with native invoke * * @requires vm.flavor == "server" - * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | + os.arch == "aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" * @requires vm.gc.Shenandoah * * @run main/native/othervm --enable-native-access=ALL-UNNAMED -XX:+UnlockDiagnosticVMOptions From 9e240554194e9c2be2425eb983d248923c217da5 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 3 Mar 2026 06:49:10 +0000 Subject: [PATCH 018/170] 8372246: LogOutputList gtests should not use LogConfiguration LogOutputs Reviewed-by: jsjolen, aartemov --- .../gtest/logging/test_logOutputList.cpp | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/test/hotspot/gtest/logging/test_logOutputList.cpp b/test/hotspot/gtest/logging/test_logOutputList.cpp index 64becbd7ef7..df3bb2c3227 100644 --- a/test/hotspot/gtest/logging/test_logOutputList.cpp +++ b/test/hotspot/gtest/logging/test_logOutputList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,16 @@ static LogOutput* dummy_output(size_t id) { return reinterpret_cast(id + 1); } +static LogStdoutOutput* dummy_stdout() { + static LogStdoutOutput dummy_stdout; + return &dummy_stdout; +} + +static LogStderrOutput* dummy_stderr() { + static LogStderrOutput dummy_stderr; + return &dummy_stderr; +} + // Randomly update and verify some outputs some number of times TEST(LogOutputList, set_output_level_update) { const size_t TestOutputCount = 10; @@ -174,7 +184,7 @@ TEST(LogOutputList, is_level_single_output) { for (size_t i = LogLevel::First; i < LogLevel::Count; i++) { LogLevelType level = static_cast(i); LogOutputList list; - list.set_output_level(LogConfiguration::StdoutLog, level); + list.set_output_level(dummy_stdout(), level); for (size_t j = LogLevel::First; j < LogLevel::Count; j++) { LogLevelType other = static_cast(j); // Verify that levels finer than the current level for stdout are reported as disabled, @@ -202,8 +212,8 @@ TEST(LogOutputList, is_level_empty) { // Test is_level() on lists with two outputs on different levels TEST(LogOutputList, is_level_multiple_outputs) { for (size_t i = LogLevel::First; i < LogLevel::Count - 1; i++) { - LogOutput* dummy1 = LogConfiguration::StdoutLog; - LogOutput* dummy2 = LogConfiguration::StderrLog; + LogOutput* dummy1 = dummy_stdout(); + LogOutput* dummy2 = dummy_stderr(); LogLevelType first = static_cast(i); LogLevelType second = static_cast(i + 1); LogOutputList list; @@ -227,19 +237,19 @@ TEST(LogOutputList, level_for) { LogOutputList list; // Ask the empty list about stdout, stderr - EXPECT_EQ(LogLevel::Off, list.level_for(LogConfiguration::StdoutLog)); - EXPECT_EQ(LogLevel::Off, list.level_for(LogConfiguration::StderrLog)); + EXPECT_EQ(LogLevel::Off, list.level_for(dummy_stdout())); + EXPECT_EQ(LogLevel::Off, list.level_for(dummy_stderr())); // Ask for level in a list with two outputs on different levels - list.set_output_level(LogConfiguration::StdoutLog, LogLevel::Info); - list.set_output_level(LogConfiguration::StderrLog, LogLevel::Trace); - EXPECT_EQ(LogLevel::Info, list.level_for(LogConfiguration::StdoutLog)); - EXPECT_EQ(LogLevel::Trace, list.level_for(LogConfiguration::StderrLog)); + list.set_output_level(dummy_stdout(), LogLevel::Info); + list.set_output_level(dummy_stderr(), LogLevel::Trace); + EXPECT_EQ(LogLevel::Info, list.level_for(dummy_stdout())); + EXPECT_EQ(LogLevel::Trace, list.level_for(dummy_stderr())); // Remove and ask again - list.set_output_level(LogConfiguration::StdoutLog, LogLevel::Off); - EXPECT_EQ(LogLevel::Off, list.level_for(LogConfiguration::StdoutLog)); - EXPECT_EQ(LogLevel::Trace, list.level_for(LogConfiguration::StderrLog)); + list.set_output_level(dummy_stdout(), LogLevel::Off); + EXPECT_EQ(LogLevel::Off, list.level_for(dummy_stdout())); + EXPECT_EQ(LogLevel::Trace, list.level_for(dummy_stderr())); // Ask about an unknown output LogOutput* dummy = dummy_output(4711); @@ -252,5 +262,5 @@ TEST(LogOutputList, level_for) { } // Make sure the stderr level is still the same - EXPECT_EQ(LogLevel::Trace, list.level_for(LogConfiguration::StderrLog)); + EXPECT_EQ(LogLevel::Trace, list.level_for(dummy_stderr())); } From 545cf60763feba343b8eed42332a8dc0e51c50f6 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 3 Mar 2026 06:49:24 +0000 Subject: [PATCH 019/170] 8372242: Gtest LogTagSet.defaults should run in OTHER VM Reviewed-by: jsjolen, aartemov --- test/hotspot/gtest/logging/test_logTagSet.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/hotspot/gtest/logging/test_logTagSet.cpp b/test/hotspot/gtest/logging/test_logTagSet.cpp index 4c00644d25b..b53272eafdb 100644 --- a/test/hotspot/gtest/logging/test_logTagSet.cpp +++ b/test/hotspot/gtest/logging/test_logTagSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,9 @@ #include "utilities/ostream.hpp" #include "unittest.hpp" -// Test the default level for each tagset -TEST_VM(LogTagSet, defaults) { +// Test the default level for each tagset, runs in other VM to ensure no other +// test have changed a LogTagSet. +TEST_OTHER_VM(LogTagSet, defaults) { for (LogTagSet* ts = LogTagSet::first(); ts != nullptr; ts = ts->next()) { char buf[256]; ts->label(buf, sizeof(buf)); From f4da2d56b7785569e1b88625bb766675b20438cc Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Tue, 3 Mar 2026 08:38:42 +0000 Subject: [PATCH 020/170] 8378684: Fix -Wdeprecated-declarations warnings from gtest by clang23 Reviewed-by: erikj, kbarrett --- make/hotspot/lib/CompileGtest.gmk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/make/hotspot/lib/CompileGtest.gmk b/make/hotspot/lib/CompileGtest.gmk index 327014b1e9d..4b21d481049 100644 --- a/make/hotspot/lib/CompileGtest.gmk +++ b/make/hotspot/lib/CompileGtest.gmk @@ -63,6 +63,10 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \ unused-result zero-as-null-pointer-constant, \ DISABLED_WARNINGS_clang := format-nonliteral undef unused-result \ zero-as-null-pointer-constant, \ + $(comment Disable deprecated-declarations warnings to workaround) \ + $(comment clang18+glibc12 bug https://github.com/llvm/llvm-project/issues/76515) \ + $(comment until the clang bug has been fixed) \ + DISABLED_WARNINGS_clang_gtest-all.cc := deprecated-declarations, \ DISABLED_WARNINGS_microsoft := 4530, \ DEFAULT_CFLAGS := false, \ CFLAGS := $(JVM_CFLAGS) \ From 7e9e64966b47c788c91f934b5fca5cd31ad465b3 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Tue, 3 Mar 2026 08:39:04 +0000 Subject: [PATCH 021/170] 8378083: Mark shenandoah/generational/TestOldGrowthTriggers.java as flagless Reviewed-by: wkemper --- .../gc/shenandoah/generational/TestOldGrowthTriggers.java | 2 +- test/lib/jdk/test/lib/process/ProcessTools.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java index a66b9161c7e..7af81fabe13 100644 --- a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java +++ b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java @@ -27,6 +27,7 @@ * @summary Test that growth of old-gen triggers old-gen marking * @key intermittent * @requires vm.gc.Shenandoah + * @requires vm.flagless * @library /test/lib * @run driver TestOldGrowthTriggers */ @@ -34,7 +35,6 @@ import java.util.*; import java.math.BigInteger; -import jdk.test.lib.Asserts; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java index fe9c1de9f30..e7dd20c6286 100644 --- a/test/lib/jdk/test/lib/process/ProcessTools.java +++ b/test/lib/jdk/test/lib/process/ProcessTools.java @@ -575,7 +575,7 @@ public final class ProcessTools { * "test.vm.opts" and "test.java.opts" and this method will * not do that. * - *

If you still chose to use + *

If you still choose to use * createLimitedTestJavaProcessBuilder() you should probably use * it in combination with @requires vm.flagless JTREG * anotation as to not waste energy and test resources. @@ -609,7 +609,7 @@ public final class ProcessTools { * "test.vm.opts" and "test.java.opts" and this method will * not do that. * - *

If you still chose to use + *

If you still choose to use * createLimitedTestJavaProcessBuilder() you should probably use * it in combination with @requires vm.flagless JTREG * anotation as to not waste energy and test resources. From c0c8bdd294c5ca56307123c7f10ec10ba33c4bca Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 3 Mar 2026 09:23:22 +0000 Subject: [PATCH 022/170] 8378948: Remove unused local variable in RunnerGSInserterThread Reviewed-by: syan, jiefu --- test/hotspot/gtest/utilities/test_concurrentHashtable.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp b/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp index 77055e92256..8094e93b944 100644 --- a/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp +++ b/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp @@ -888,7 +888,6 @@ public: virtual ~RunnerGSInserterThread(){} void premain() { - volatile bool timeout = false; _start = START; _range = RANGE; CHTTestThread* tt[GSTEST_THREAD_COUNT]; From 0b183bf2d608bedf118607b1471fbf1e68813a08 Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Tue, 3 Mar 2026 09:39:06 +0000 Subject: [PATCH 023/170] 8312116: GenShen: make instantaneous allocation rate triggers more timely Reviewed-by: wkemper --- .../shenandoahAdaptiveHeuristics.cpp | 559 ++++++++++++++++-- .../shenandoahAdaptiveHeuristics.hpp | 76 +++ .../shenandoahGenerationalHeuristics.cpp | 6 + .../shenandoahGenerationalHeuristics.hpp | 2 + .../heuristics/shenandoahHeuristics.cpp | 30 +- .../heuristics/shenandoahHeuristics.hpp | 33 +- .../heuristics/shenandoahYoungHeuristics.cpp | 3 +- .../gc/shenandoah/shenandoahConcurrentGC.cpp | 1 + .../gc/shenandoah/shenandoahControlThread.cpp | 19 +- .../gc/shenandoah/shenandoahDegeneratedGC.cpp | 1 + .../share/gc/shenandoah/shenandoahFreeSet.cpp | 62 +- .../share/gc/shenandoah/shenandoahFreeSet.hpp | 70 ++- .../share/gc/shenandoah/shenandoahFullGC.cpp | 4 +- .../gc/shenandoah/shenandoahGeneration.cpp | 7 +- .../gc/shenandoah/shenandoahGeneration.hpp | 2 +- .../shenandoahGenerationalControlThread.cpp | 3 +- .../shenandoah/shenandoahGenerationalHeap.cpp | 22 +- .../shenandoah/shenandoahGenerationalHeap.hpp | 3 + .../share/gc/shenandoah/shenandoahHeap.cpp | 27 +- .../share/gc/shenandoah/shenandoahHeap.hpp | 3 + .../gc/shenandoah/shenandoahOldGeneration.cpp | 2 + .../shenandoah/shenandoahRegulatorThread.cpp | 16 +- .../shenandoah/shenandoahRegulatorThread.hpp | 3 + .../gc/shenandoah/shenandoah_globals.hpp | 53 ++ 24 files changed, 899 insertions(+), 108 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index 7a8bd55c795..ac8b3ebdf37 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -33,6 +33,7 @@ #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" +#include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "logging/log.hpp" #include "logging/logTag.hpp" #include "runtime/globals.hpp" @@ -59,14 +60,95 @@ const double ShenandoahAdaptiveHeuristics::HIGHEST_EXPECTED_AVAILABLE_AT_END = 0 const double ShenandoahAdaptiveHeuristics::MINIMUM_CONFIDENCE = 0.319; // 25% const double ShenandoahAdaptiveHeuristics::MAXIMUM_CONFIDENCE = 3.291; // 99.9% + +// To enable detection of GC time trends, we keep separate track of the recent history of gc time. During initialization, +// for example, the amount of live memory may be increasing, which is likely to cause the GC times to increase. This history +// allows us to predict increasing GC times rather than always assuming average recent GC time is the best predictor. +const size_t ShenandoahAdaptiveHeuristics::GC_TIME_SAMPLE_SIZE = 3; + +// We also keep separate track of recently sampled allocation rates for two purposes: +// 1. The number of samples examined to determine acceleration of allocation is represented by +// ShenandoahRateAccelerationSampleSize +// 2. The number of most recent samples averaged to determine a momentary allocation spike is represented by +// ShenandoahMomentaryAllocationRateSpikeSampleSize + +// Allocation rates are sampled by the regulator thread, which typically runs every ms. There may be jitter in the scheduling +// of the regulator thread. To reduce signal noise and synchronization overhead, we do not sample allocation rate with every +// iteration of the regulator. We prefer sample time longer than 1 ms so that there can be a statistically significant number +// of allocations occuring within each sample period. The regulator thread samples allocation rate only if at least +// ShenandoahAccelerationSamplePeriod ms have passed since it previously sampled the allocation rate. +// +// This trigger responds much more quickly than the traditional trigger, which monitors 100 ms spans. When acceleration is +// detected, the impact of acceleration on anticipated consumption of available memory is also much more impactful +// than the assumed constant allocation rate consumption of available memory. + ShenandoahAdaptiveHeuristics::ShenandoahAdaptiveHeuristics(ShenandoahSpaceInfo* space_info) : ShenandoahHeuristics(space_info), _margin_of_error_sd(ShenandoahAdaptiveInitialConfidence), _spike_threshold_sd(ShenandoahAdaptiveInitialSpikeThreshold), _last_trigger(OTHER), - _available(Moving_Average_Samples, ShenandoahAdaptiveDecayFactor) { } + _available(Moving_Average_Samples, ShenandoahAdaptiveDecayFactor), + _free_set(nullptr), + _previous_acceleration_sample_timestamp(0.0), + _gc_time_first_sample_index(0), + _gc_time_num_samples(0), + _gc_time_timestamps(NEW_C_HEAP_ARRAY(double, GC_TIME_SAMPLE_SIZE, mtGC)), + _gc_time_samples(NEW_C_HEAP_ARRAY(double, GC_TIME_SAMPLE_SIZE, mtGC)), + _gc_time_xy(NEW_C_HEAP_ARRAY(double, GC_TIME_SAMPLE_SIZE, mtGC)), + _gc_time_xx(NEW_C_HEAP_ARRAY(double, GC_TIME_SAMPLE_SIZE, mtGC)), + _gc_time_sum_of_timestamps(0), + _gc_time_sum_of_samples(0), + _gc_time_sum_of_xy(0), + _gc_time_sum_of_xx(0), + _gc_time_m(0.0), + _gc_time_b(0.0), + _gc_time_sd(0.0), + _spike_acceleration_buffer_size(MAX2(ShenandoahRateAccelerationSampleSize, 1+ShenandoahMomentaryAllocationRateSpikeSampleSize)), + _spike_acceleration_first_sample_index(0), + _spike_acceleration_num_samples(0), + _spike_acceleration_rate_samples(NEW_C_HEAP_ARRAY(double, _spike_acceleration_buffer_size, mtGC)), + _spike_acceleration_rate_timestamps(NEW_C_HEAP_ARRAY(double, _spike_acceleration_buffer_size, mtGC)) { + } -ShenandoahAdaptiveHeuristics::~ShenandoahAdaptiveHeuristics() {} +ShenandoahAdaptiveHeuristics::~ShenandoahAdaptiveHeuristics() { + FREE_C_HEAP_ARRAY(double, _spike_acceleration_rate_samples); + FREE_C_HEAP_ARRAY(double, _spike_acceleration_rate_timestamps); + FREE_C_HEAP_ARRAY(double, _gc_time_timestamps); + FREE_C_HEAP_ARRAY(double, _gc_time_samples); + FREE_C_HEAP_ARRAY(double, _gc_time_xy); + FREE_C_HEAP_ARRAY(double, _gc_time_xx); +} + +void ShenandoahAdaptiveHeuristics::initialize() { + ShenandoahHeuristics::initialize(); +} + +void ShenandoahAdaptiveHeuristics::post_initialize() { + ShenandoahHeuristics::post_initialize(); + _free_set = ShenandoahHeap::heap()->free_set(); + assert(!ShenandoahHeap::heap()->mode()->is_generational(), "ShenandoahGenerationalHeuristics overrides this method"); + compute_headroom_adjustment(); +} + +void ShenandoahAdaptiveHeuristics::compute_headroom_adjustment() { + // The trigger threshold represents mutator available - "head room". + // We plan for GC to finish before the amount of allocated memory exceeds trigger threshold. This is the same as saying we + // intend to finish GC before the amount of available memory is less than the allocation headroom. Headroom is the planned + // safety buffer to allow a small amount of additional allocation to take place in case we were overly optimistic in delaying + // our trigger. + size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); + size_t spike_headroom = capacity / 100 * ShenandoahAllocSpikeFactor; + size_t penalties = capacity / 100 * _gc_time_penalties; + _headroom_adjustment = spike_headroom + penalties; +} + +void ShenandoahAdaptiveHeuristics::start_idle_span() { + compute_headroom_adjustment(); +} + +void ShenandoahAdaptiveHeuristics::adjust_penalty(intx step) { + ShenandoahHeuristics::adjust_penalty(step); +} void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(ShenandoahCollectionSet* cset, RegionData* data, size_t size, @@ -76,8 +158,8 @@ void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(Shenand // The logic for cset selection in adaptive is as follows: // // 1. We cannot get cset larger than available free space. Otherwise we guarantee OOME - // during evacuation, and thus guarantee full GC. In practice, we also want to let - // application to allocate something. This is why we limit CSet to some fraction of + // during evacuation, and thus guarantee full GC. In practice, we also want to let the + // application allocate during concurrent GC. This is why we limit CSet to some fraction of // available space. In non-overloaded heap, max_cset would contain all plausible candidates // over garbage threshold. // @@ -108,6 +190,7 @@ void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(Shenand size_t cur_cset = 0; size_t cur_garbage = 0; + // Regions are sorted in order of decreasing garbage for (size_t idx = 0; idx < size; idx++) { ShenandoahHeapRegion* r = data[idx].get_region(); @@ -126,6 +209,88 @@ void ShenandoahAdaptiveHeuristics::choose_collection_set_from_regiondata(Shenand } } +void ShenandoahAdaptiveHeuristics::add_degenerated_gc_time(double timestamp, double gc_time) { + // Conservatively add sample into linear model If this time is above the predicted concurrent gc time + if (predict_gc_time(timestamp) < gc_time) { + add_gc_time(timestamp, gc_time); + } +} + +void ShenandoahAdaptiveHeuristics::add_gc_time(double timestamp, double gc_time) { + // Update best-fit linear predictor of GC time + uint index = (_gc_time_first_sample_index + _gc_time_num_samples) % GC_TIME_SAMPLE_SIZE; + if (_gc_time_num_samples == GC_TIME_SAMPLE_SIZE) { + _gc_time_sum_of_timestamps -= _gc_time_timestamps[index]; + _gc_time_sum_of_samples -= _gc_time_samples[index]; + _gc_time_sum_of_xy -= _gc_time_xy[index]; + _gc_time_sum_of_xx -= _gc_time_xx[index]; + } + _gc_time_timestamps[index] = timestamp; + _gc_time_samples[index] = gc_time; + _gc_time_xy[index] = timestamp * gc_time; + _gc_time_xx[index] = timestamp * timestamp; + + _gc_time_sum_of_timestamps += _gc_time_timestamps[index]; + _gc_time_sum_of_samples += _gc_time_samples[index]; + _gc_time_sum_of_xy += _gc_time_xy[index]; + _gc_time_sum_of_xx += _gc_time_xx[index]; + + if (_gc_time_num_samples < GC_TIME_SAMPLE_SIZE) { + _gc_time_num_samples++; + } else { + _gc_time_first_sample_index = (_gc_time_first_sample_index + 1) % GC_TIME_SAMPLE_SIZE; + } + + if (_gc_time_num_samples == 1) { + // The predictor is constant (horizontal line) + _gc_time_m = 0; + _gc_time_b = gc_time; + _gc_time_sd = 0.0; + } else if (_gc_time_num_samples == 2) { + // Two points define a line + double delta_y = gc_time - _gc_time_samples[_gc_time_first_sample_index]; + double delta_x = timestamp - _gc_time_timestamps[_gc_time_first_sample_index]; + _gc_time_m = delta_y / delta_x; + + // y = mx + b + // so b = y0 - mx0 + _gc_time_b = gc_time - _gc_time_m * timestamp; + _gc_time_sd = 0.0; + } else { + _gc_time_m = ((_gc_time_num_samples * _gc_time_sum_of_xy - _gc_time_sum_of_timestamps * _gc_time_sum_of_samples) / + (_gc_time_num_samples * _gc_time_sum_of_xx - _gc_time_sum_of_timestamps * _gc_time_sum_of_timestamps)); + _gc_time_b = (_gc_time_sum_of_samples - _gc_time_m * _gc_time_sum_of_timestamps) / _gc_time_num_samples; + double sum_of_squared_deviations = 0.0; + for (size_t i = 0; i < _gc_time_num_samples; i++) { + uint index = (_gc_time_first_sample_index + i) % GC_TIME_SAMPLE_SIZE; + double x = _gc_time_timestamps[index]; + double predicted_y = _gc_time_m * x + _gc_time_b; + double deviation = predicted_y - _gc_time_samples[index]; + sum_of_squared_deviations += deviation * deviation; + } + _gc_time_sd = sqrt(sum_of_squared_deviations / _gc_time_num_samples); + } +} + +double ShenandoahAdaptiveHeuristics::predict_gc_time(double timestamp_at_start) { + return _gc_time_m * timestamp_at_start + _gc_time_b + _gc_time_sd * _margin_of_error_sd;; +} + +void ShenandoahAdaptiveHeuristics::add_rate_to_acceleration_history(double timestamp, double rate) { + uint new_sample_index = + (_spike_acceleration_first_sample_index + _spike_acceleration_num_samples) % _spike_acceleration_buffer_size; + _spike_acceleration_rate_timestamps[new_sample_index] = timestamp; + _spike_acceleration_rate_samples[new_sample_index] = rate; + if (_spike_acceleration_num_samples == _spike_acceleration_buffer_size) { + _spike_acceleration_first_sample_index++; + if (_spike_acceleration_first_sample_index == _spike_acceleration_buffer_size) { + _spike_acceleration_first_sample_index = 0; + } + } else { + _spike_acceleration_num_samples++; + } +} + void ShenandoahAdaptiveHeuristics::record_cycle_start() { ShenandoahHeuristics::record_cycle_start(); _allocation_rate.allocation_counter_reset(); @@ -133,6 +298,10 @@ void ShenandoahAdaptiveHeuristics::record_cycle_start() { void ShenandoahAdaptiveHeuristics::record_success_concurrent() { ShenandoahHeuristics::record_success_concurrent(); + double now = os::elapsedTime(); + + // Should we not add GC time if this was an abbreviated cycle? + add_gc_time(_cycle_start, elapsed_cycle_time()); size_t available = _space_info->available(); @@ -185,6 +354,7 @@ void ShenandoahAdaptiveHeuristics::record_success_concurrent() { void ShenandoahAdaptiveHeuristics::record_degenerated() { ShenandoahHeuristics::record_degenerated(); + add_degenerated_gc_time(_precursor_cycle_start, elapsed_degenerated_cycle_time()); // Adjust both trigger's parameters in the case of a degenerated GC because // either of them should have triggered earlier to avoid this case. adjust_margin_of_error(DEGENERATE_PENALTY_SD); @@ -236,6 +406,24 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() { size_t available = _space_info->soft_mutator_available(); size_t allocated = _space_info->bytes_allocated_since_gc_start(); + double avg_cycle_time = 0; + double avg_alloc_rate = 0; + double now = get_most_recent_wake_time(); + size_t allocatable_words = this->allocatable(available); + double predicted_future_accelerated_gc_time = 0.0; + size_t allocated_bytes_since_last_sample = 0; + double instantaneous_rate_words_per_second = 0.0; + size_t consumption_accelerated = 0; + double acceleration = 0.0; + double current_rate_by_acceleration = 0.0; + size_t min_threshold = min_free_threshold(); + double predicted_future_gc_time = 0; + double future_planned_gc_time = 0; + bool future_planned_gc_time_is_average = false; + double avg_time_to_deplete_available = 0.0; + bool is_spiking = false; + double spike_time_to_deplete_available = 0.0; + log_debug(gc, ergo)("should_start_gc calculation: available: " PROPERFMT ", soft_max_capacity: " PROPERFMT ", " "allocated_since_gc_start: " PROPERFMT, PROPERFMTARGS(available), PROPERFMTARGS(capacity), PROPERFMTARGS(allocated)); @@ -250,7 +438,6 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() { _last_trigger = OTHER; - size_t min_threshold = min_free_threshold(); if (available < min_threshold) { log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")", PROPERFMTARGS(available), PROPERFMTARGS(min_threshold)); @@ -271,55 +458,227 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() { return true; } } - // Check if allocation headroom is still okay. This also factors in: - // 1. Some space to absorb allocation spikes (ShenandoahAllocSpikeFactor) - // 2. Accumulated penalties from Degenerated and Full GC - size_t allocation_headroom = available; - size_t spike_headroom = capacity / 100 * ShenandoahAllocSpikeFactor; - size_t penalties = capacity / 100 * _gc_time_penalties; + // The test (3 * allocated > available) below is intended to prevent triggers from firing so quickly that there + // has not been sufficient time to create garbage that can be reclaimed during the triggered GC cycle. If we trigger before + // garbage has been created, the concurrent GC will find no garbage. This has been observed to result in degens which + // experience OOM during evac or that experience "bad progress", both of which escalate to Full GC. Note that garbage that + // was allocated following the start of the current GC cycle cannot be reclaimed in this GC cycle. Here is the derivation + // of the expression: + // + // Let R (runway) represent the total amount of memory that can be allocated following the start of GC(N). The runway + // represents memory available at the start of the current GC plus garbage reclaimed by the current GC. In a balanced, + // fully utilized configuration, we will be starting each new GC cycle immediately following completion of the preceding + // GC cycle. In this configuration, we would expect half of R to be consumed during concurrent cycle GC(N) and half + // to be consumed during concurrent GC(N+1). + // + // Assume we want to delay GC trigger until: A/V > 0.33 + // This is equivalent to enforcing that: A > 0.33V + // which is: 3A > V + // Since A+V equals R, we have: A + 3A > A + V = R + // which is to say that: A > R/4 + // + // Postponing the trigger until at least 1/4 of the runway has been consumed helps to improve the efficiency of the + // triggered GC. Under heavy steady state workload, this delay condition generally has no effect: if the allocation + // runway is divided "equally" between the current GC and the next GC, then at any potential trigger point (which cannot + // happen any sooner than completion of the first GC), it is already the case that roughly A > R/2. + if (3 * allocated <= available) { + // Even though we will not issue an adaptive trigger unless a minimum threshold of memory has been allocated, + // we still allow more generic triggers, such as guaranteed GC intervals, to act. + return ShenandoahHeuristics::should_start_gc(); + } - allocation_headroom -= MIN2(allocation_headroom, spike_headroom); - allocation_headroom -= MIN2(allocation_headroom, penalties); + avg_cycle_time = _gc_cycle_time_history->davg() + (_margin_of_error_sd * _gc_cycle_time_history->dsd()); + avg_alloc_rate = _allocation_rate.upper_bound(_margin_of_error_sd); + if ((now - _previous_acceleration_sample_timestamp) >= (ShenandoahAccelerationSamplePeriod / 1000.0)) { + predicted_future_accelerated_gc_time = + predict_gc_time(now + MAX2(get_planned_sleep_interval(), ShenandoahAccelerationSamplePeriod / 1000.0)); + double future_accelerated_planned_gc_time; + bool future_accelerated_planned_gc_time_is_average; + if (predicted_future_accelerated_gc_time > avg_cycle_time) { + future_accelerated_planned_gc_time = predicted_future_accelerated_gc_time; + future_accelerated_planned_gc_time_is_average = false; + } else { + future_accelerated_planned_gc_time = avg_cycle_time; + future_accelerated_planned_gc_time_is_average = true; + } + allocated_bytes_since_last_sample = _free_set->get_bytes_allocated_since_previous_sample(); + instantaneous_rate_words_per_second = + (allocated_bytes_since_last_sample / HeapWordSize) / (now - _previous_acceleration_sample_timestamp); - double avg_cycle_time = _gc_cycle_time_history->davg() + (_margin_of_error_sd * _gc_cycle_time_history->dsd()); - double avg_alloc_rate = _allocation_rate.upper_bound(_margin_of_error_sd); + _previous_acceleration_sample_timestamp = now; + add_rate_to_acceleration_history(now, instantaneous_rate_words_per_second); + current_rate_by_acceleration = instantaneous_rate_words_per_second; + consumption_accelerated = + accelerated_consumption(acceleration, current_rate_by_acceleration, avg_alloc_rate / HeapWordSize, + (ShenandoahAccelerationSamplePeriod / 1000.0) + future_accelerated_planned_gc_time); - log_debug(gc)("average GC time: %.2f ms, allocation rate: %.0f %s/s", - avg_cycle_time * 1000, byte_size_in_proper_unit(avg_alloc_rate), proper_unit_for_byte_size(avg_alloc_rate)); - if (avg_cycle_time * avg_alloc_rate > allocation_headroom) { - log_trigger("Average GC time (%.2f ms) is above the time for average allocation rate (%.0f %sB/s)" - " to deplete free headroom (%zu%s) (margin of error = %.2f)", - avg_cycle_time * 1000, - byte_size_in_proper_unit(avg_alloc_rate), proper_unit_for_byte_size(avg_alloc_rate), - byte_size_in_proper_unit(allocation_headroom), proper_unit_for_byte_size(allocation_headroom), - _margin_of_error_sd); - log_info(gc, ergo)("Free headroom: %zu%s (free) - %zu%s (spike) - %zu%s (penalties) = %zu%s", - byte_size_in_proper_unit(available), proper_unit_for_byte_size(available), - byte_size_in_proper_unit(spike_headroom), proper_unit_for_byte_size(spike_headroom), - byte_size_in_proper_unit(penalties), proper_unit_for_byte_size(penalties), - byte_size_in_proper_unit(allocation_headroom), proper_unit_for_byte_size(allocation_headroom)); + // Note that even a single thread that wakes up and begins to allocate excessively can manifest as accelerating allocation + // rate. This thread will initially allocate a TLAB of minimum size. Then it will allocate a TLAB twice as big a bit later, + // and then twice as big again after another short delay. When a phase change causes many threads to increase their + // allocation behavior, this effect is multiplied, and compounded by jitter in the times that individual threads experience + // the phase change. + // + // The following trace represents an actual workload, with allocation rates sampled at 10 Hz, the default behavior before + // introduction of accelerated allocation rate detection. Though the allocation rate is seen to be increasing at times + // 101.907 and 102.007 and 102.108, the newly sampled allocation rate is not enough to trigger GC because the headroom is + // still quite large. In fact, GC is not triggered until time 102.409s, and this GC degenerates. + // + // Sample Time (s) Allocation Rate (MB/s) Headroom (GB) + // 101.807 0.0 26.93 + // <--- accelerated spike can trigger here, around time 101.9s + // 101.907 477.6 26.85 + // 102.007 3,206.0 26.35 + // 102.108 23,797.8 24.19 + // 102.208 24,164.5 21.83 + // 102.309 23,965.0 19.47 + // 102.409 24,624.35 17.05 <--- without accelerated rate detection, we trigger here + // + // Though the above measurements are from actual workload, the following details regarding sampled allocation rates at 3ms + // period were not measured directly for this run-time sample. These are hypothetical, though they represent a plausible + // result that correlates with the actual measurements. + // + // For most of the 100 ms time span that precedes the sample at 101.907, the allocation rate still remains at zero. The phase + // change that causes increasing allocations occurs near the end ot this time segment. When sampled with a 3 ms period, + // acceration of allocation can be triggered at approximately time 101.88s. + // + // In the default configuration, accelerated allocation rate is detected by examining a sequence of 8 allocation rate samples. + // + // Even a single allocation rate sample above the norm can be interpreted as acceleration of allocation rate. For example, the + // the best-fit line for the following samples has an acceleration rate of 3,553.3 MB/s/s. This is not enough to trigger GC, + // especially given the abundance of Headroom at this moment in time. + // + // TimeStamp (s) Alloc rate (MB/s) + // 101.857 0 + // 101.860 0 + // 101.863 0 + // 101.866 0 + // 101.869 53.3 + // + // At the next sample time, we will compute a slightly higher acceration, 9,150 MB/s/s. This is also insufficient to trigger + // GC. + // + // TimeStamp (s) Alloc rate (MB/s) + // 101.860 0 + // 101.863 0 + // 101.866 0 + // 101.869 53.3 + // 101.872 110.6 + // + // Eventually, we will observe a full history of accelerating rate samples, computing acceleration of 18,500 MB/s/s. This will + // trigger GC over 500 ms earlier than was previously possible. + // + // TimeStamp (s) Alloc rate (MB/s) + // 101.866 0 + // 101.869 53.3 + // 101.872 110.6 + // 101.875 165.9 + // 101.878 221.2 + // + // The accelerated rate heuristic is based on the following idea: + // + // Assume allocation rate is accelerating at a constant rate. If we postpone the spike trigger until the subsequent + // sample point, will there be enough memory to satisfy allocations that occur during the anticipated concurrent GC + // cycle? If not, we should trigger right now. + // + // Outline of this heuristic triggering technique: + // + // 1. We remember the N (e.g. N=3) most recent samples of spike allocation rate r0, r1, r2 samples at t0, t1, and t2 + // 2. if r1 < r0 or r2 < r1, approximate Acceleration = 0.0, Rate = Average(r0, r1, r2) + // 3. Otherwise, use least squares method to compute best-fit line of rate vs time + // 4. The slope of this line represents Acceleration. The y-intercept of this line represents "initial rate" + // 5. Use r2 to rrpresent CurrentRate + // 6. Use Consumption = CurrentRate * GCTime + 1/2 * Acceleration * GCTime * GCTime + // (See High School physics discussions on constant acceleration: D = v0 * t + 1/2 * a * t^2) + // 7. if Consumption exceeds headroom, trigger now + // + // Though larger sample size may improve quality of predictor, it also delays trigger response. Smaller sample sizes + // are more susceptible to false triggers based on random noise. The default configuration uses a sample size of 8 and + // a sample period of roughly 15 ms, spanning approximately 120 ms of execution. + if (consumption_accelerated > allocatable_words) { + size_t size_t_alloc_rate = (size_t) current_rate_by_acceleration * HeapWordSize; + if (acceleration > 0) { + size_t size_t_acceleration = (size_t) acceleration * HeapWordSize; + log_trigger("Accelerated consumption (" PROPERFMT ") exceeds free headroom (" PROPERFMT ") at " + "current rate (" PROPERFMT "/s) with acceleration (" PROPERFMT "/s/s) for planned %s GC time (%.2f ms)", + PROPERFMTARGS(consumption_accelerated * HeapWordSize), + PROPERFMTARGS(allocatable_words * HeapWordSize), + PROPERFMTARGS(size_t_alloc_rate), + PROPERFMTARGS(size_t_acceleration), + future_accelerated_planned_gc_time_is_average? "(from average)": "(by linear prediction)", + future_accelerated_planned_gc_time * 1000); + } else { + log_trigger("Momentary spike consumption (" PROPERFMT ") exceeds free headroom (" PROPERFMT ") at " + "current rate (" PROPERFMT "/s) for planned %s GC time (%.2f ms) (spike threshold = %.2f)", + PROPERFMTARGS(consumption_accelerated * HeapWordSize), + PROPERFMTARGS(allocatable_words * HeapWordSize), + PROPERFMTARGS(size_t_alloc_rate), + future_accelerated_planned_gc_time_is_average? "(from average)": "(by linear prediction)", + future_accelerated_planned_gc_time * 1000, _spike_threshold_sd); + + + } + _spike_acceleration_num_samples = 0; + _spike_acceleration_first_sample_index = 0; + + // Count this as a form of RATE trigger for purposes of adjusting heuristic triggering configuration because this + // trigger is influenced more by margin_of_error_sd than by spike_threshold_sd. + accept_trigger_with_type(RATE); + return true; + } + } + + // Suppose we don't trigger now, but decide to trigger in the next regulator cycle. What will be the GC time then? + predicted_future_gc_time = predict_gc_time(now + get_planned_sleep_interval()); + if (predicted_future_gc_time > avg_cycle_time) { + future_planned_gc_time = predicted_future_gc_time; + future_planned_gc_time_is_average = false; + } else { + future_planned_gc_time = avg_cycle_time; + future_planned_gc_time_is_average = true; + } + + log_debug(gc)("%s: average GC time: %.2f ms, predicted GC time: %.2f ms, allocation rate: %.0f %s/s", + _space_info->name(), avg_cycle_time * 1000, predicted_future_gc_time * 1000, + byte_size_in_proper_unit(avg_alloc_rate), proper_unit_for_byte_size(avg_alloc_rate)); + size_t allocatable_bytes = allocatable_words * HeapWordSize; + avg_time_to_deplete_available = allocatable_bytes / avg_alloc_rate; + + if (future_planned_gc_time > avg_time_to_deplete_available) { + log_trigger("%s GC time (%.2f ms) is above the time for average allocation rate (%.0f %sB/s)" + " to deplete free headroom (%zu%s) (margin of error = %.2f)", + future_planned_gc_time_is_average? "Average": "Linear prediction of", future_planned_gc_time * 1000, + byte_size_in_proper_unit(avg_alloc_rate), proper_unit_for_byte_size(avg_alloc_rate), + byte_size_in_proper_unit(allocatable_bytes), proper_unit_for_byte_size(allocatable_bytes), + _margin_of_error_sd); + + size_t spike_headroom = capacity / 100 * ShenandoahAllocSpikeFactor; + size_t penalties = capacity / 100 * _gc_time_penalties; + size_t allocation_headroom = available; + allocation_headroom -= MIN2(allocation_headroom, spike_headroom); + allocation_headroom -= MIN2(allocation_headroom, penalties); + log_info(gc, ergo)("Free headroom: " PROPERFMT " (free) - " PROPERFMT "(spike) - " PROPERFMT " (penalties) = " PROPERFMT, + PROPERFMTARGS(available), + PROPERFMTARGS(spike_headroom), + PROPERFMTARGS(penalties), + PROPERFMTARGS(allocation_headroom)); accept_trigger_with_type(RATE); return true; } - bool is_spiking = _allocation_rate.is_spiking(rate, _spike_threshold_sd); - if (is_spiking && avg_cycle_time > allocation_headroom / rate) { - log_trigger("Average GC time (%.2f ms) is above the time for instantaneous allocation rate (%.0f %sB/s) to deplete free headroom (%zu%s) (spike threshold = %.2f)", - avg_cycle_time * 1000, - byte_size_in_proper_unit(rate), proper_unit_for_byte_size(rate), - byte_size_in_proper_unit(allocation_headroom), proper_unit_for_byte_size(allocation_headroom), - _spike_threshold_sd); + is_spiking = _allocation_rate.is_spiking(rate, _spike_threshold_sd); + spike_time_to_deplete_available = (rate == 0)? 0: allocatable_bytes / rate; + if (is_spiking && (rate != 0) && (future_planned_gc_time > spike_time_to_deplete_available)) { + log_trigger("%s GC time (%.2f ms) is above the time for instantaneous allocation rate (%.0f %sB/s)" + " to deplete free headroom (%zu%s) (spike threshold = %.2f)", + future_planned_gc_time_is_average? "Average": "Linear prediction of", future_planned_gc_time * 1000, + byte_size_in_proper_unit(rate), proper_unit_for_byte_size(rate), + byte_size_in_proper_unit(allocatable_bytes), proper_unit_for_byte_size(allocatable_bytes), + _spike_threshold_sd); accept_trigger_with_type(SPIKE); return true; } - - if (ShenandoahHeuristics::should_start_gc()) { - _start_gc_is_pending = true; - return true; - } else { - return false; - } + return ShenandoahHeuristics::should_start_gc(); } void ShenandoahAdaptiveHeuristics::adjust_last_trigger_parameters(double amount) { @@ -352,6 +711,112 @@ size_t ShenandoahAdaptiveHeuristics::min_free_threshold() { return ShenandoahHeap::heap()->soft_max_capacity() / 100 * ShenandoahMinFreeThreshold; } +// This is called each time a new rate sample has been gathered, as governed by ShenandoahAccelerationSamplePeriod. +// Unlike traditional calculation of average allocation rate, there is no adjustment for standard deviation of the +// accelerated rate prediction. +size_t ShenandoahAdaptiveHeuristics::accelerated_consumption(double& acceleration, double& current_rate, + double avg_alloc_rate_words_per_second, + double predicted_cycle_time) const +{ + double *x_array = (double *) alloca(ShenandoahRateAccelerationSampleSize * sizeof(double)); + double *y_array = (double *) alloca(ShenandoahRateAccelerationSampleSize * sizeof(double)); + double x_sum = 0.0; + double y_sum = 0.0; + + assert(_spike_acceleration_num_samples > 0, "At minimum, we should have sample from this period"); + + double weighted_average_alloc; + if (_spike_acceleration_num_samples >= ShenandoahRateAccelerationSampleSize) { + double weighted_y_sum = 0; + double total_weight = 0; + double previous_x = 0; + uint delta = _spike_acceleration_num_samples - ShenandoahRateAccelerationSampleSize; + for (uint i = 0; i < ShenandoahRateAccelerationSampleSize; i++) { + uint index = (_spike_acceleration_first_sample_index + delta + i) % _spike_acceleration_buffer_size; + x_array[i] = _spike_acceleration_rate_timestamps[index]; + x_sum += x_array[i]; + y_array[i] = _spike_acceleration_rate_samples[index]; + if (i > 0) { + // first sample not included in weighted average because it has no weight. + double sample_weight = x_array[i] - x_array[i-1]; + weighted_y_sum = y_array[i] * sample_weight; + total_weight += sample_weight; + } + y_sum += y_array[i]; + } + weighted_average_alloc = (total_weight > 0)? weighted_y_sum / total_weight: 0; + } else { + weighted_average_alloc = 0; + } + + double momentary_rate; + if (_spike_acceleration_num_samples > ShenandoahMomentaryAllocationRateSpikeSampleSize) { + // Num samples must be strictly greater than sample size, because we need one extra sample to compute rate and weights + // In this context, the weight of a y value (an allocation rate) is the duration for which this allocation rate was + // active (the time since previous y value was reported). An allocation rate measured over a span of 300 ms (e.g. during + // concurrent GC) has much more "weight" than an allocation rate measured over a span of 15 s. + double weighted_y_sum = 0; + double total_weight = 0; + double sum_for_average = 0.0; + uint delta = _spike_acceleration_num_samples - ShenandoahMomentaryAllocationRateSpikeSampleSize; + for (uint i = 0; i < ShenandoahMomentaryAllocationRateSpikeSampleSize; i++) { + uint sample_index = (_spike_acceleration_first_sample_index + delta + i) % _spike_acceleration_buffer_size; + uint preceding_index = (sample_index == 0)? _spike_acceleration_buffer_size - 1: sample_index - 1; + double sample_weight = (_spike_acceleration_rate_timestamps[sample_index] + - _spike_acceleration_rate_timestamps[preceding_index]); + weighted_y_sum += _spike_acceleration_rate_samples[sample_index] * sample_weight; + total_weight += sample_weight; + } + momentary_rate = weighted_y_sum / total_weight; + bool is_spiking = _allocation_rate.is_spiking(momentary_rate, _spike_threshold_sd); + if (!is_spiking) { + // Disable momentary spike trigger unless allocation rate delta from average exceeds sd + momentary_rate = 0.0; + } + } else { + momentary_rate = 0.0; + } + + // By default, use momentary_rate for current rate and zero acceleration. Overwrite iff best-fit line has positive slope. + current_rate = momentary_rate; + acceleration = 0.0; + if ((_spike_acceleration_num_samples >= ShenandoahRateAccelerationSampleSize) + && (weighted_average_alloc >= avg_alloc_rate_words_per_second)) { + // If the average rate across the acceleration samples is below the overall average, this sample is not eligible to + // represent acceleration of allocation rate. We may just be catching up with allocations after a lull. + + double *xy_array = (double *) alloca(ShenandoahRateAccelerationSampleSize * sizeof(double)); + double *x2_array = (double *) alloca(ShenandoahRateAccelerationSampleSize * sizeof(double)); + double xy_sum = 0.0; + double x2_sum = 0.0; + for (uint i = 0; i < ShenandoahRateAccelerationSampleSize; i++) { + xy_array[i] = x_array[i] * y_array[i]; + xy_sum += xy_array[i]; + x2_array[i] = x_array[i] * x_array[i]; + x2_sum += x2_array[i]; + } + // Find the best-fit least-squares linear representation of rate vs time + double m; /* slope */ + double b; /* y-intercept */ + + m = ((ShenandoahRateAccelerationSampleSize * xy_sum - x_sum * y_sum) + / (ShenandoahRateAccelerationSampleSize * x2_sum - x_sum * x_sum)); + b = (y_sum - m * x_sum) / ShenandoahRateAccelerationSampleSize; + + if (m > 0) { + double proposed_current_rate = m * x_array[ShenandoahRateAccelerationSampleSize - 1] + b; + acceleration = m; + current_rate = proposed_current_rate; + } + // else, leave current_rate = momentary_rate, acceleration = 0 + } + // and here also, leave current_rate = momentary_rate, acceleration = 0 + + double time_delta = get_planned_sleep_interval() + predicted_cycle_time; + size_t words_to_be_consumed = (size_t) (current_rate * time_delta + 0.5 * acceleration * time_delta * time_delta); + return words_to_be_consumed; +} + ShenandoahAllocationRate::ShenandoahAllocationRate() : _last_sample_time(os::elapsedTime()), _last_sample_value(0), @@ -363,7 +828,7 @@ ShenandoahAllocationRate::ShenandoahAllocationRate() : double ShenandoahAllocationRate::force_sample(size_t allocated, size_t &unaccounted_bytes_allocated) { const double MinSampleTime = 0.002; // Do not sample if time since last update is less than 2 ms double now = os::elapsedTime(); - double time_since_last_update = now -_last_sample_time; + double time_since_last_update = now - _last_sample_time; if (time_since_last_update < MinSampleTime) { unaccounted_bytes_allocated = allocated - _last_sample_value; _last_sample_value = 0; @@ -412,8 +877,10 @@ bool ShenandoahAllocationRate::is_spiking(double rate, double threshold) const { double sd = _rate.sd(); if (sd > 0) { - // There is a small chance that that rate has already been sampled, but it - // seems not to matter in practice. + // There is a small chance that that rate has already been sampled, but it seems not to matter in practice. + // Note that z_score reports how close the rate is to the average. A value between -1 and 1 means we are within one + // standard deviation. A value between -3 and +3 means we are within 3 standard deviations. We only check for z_score + // greater than threshold because we are looking for an allocation spike which is greater than the mean. double z_score = (rate - _rate.avg()) / sd; if (z_score > threshold) { return true; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp index 9b7824a50d7..c761f2a82f3 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp @@ -27,7 +27,9 @@ #define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHADAPTIVEHEURISTICS_HPP #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" +#include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" +#include "gc/shenandoah/shenandoahRegulatorThread.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "memory/allocation.hpp" #include "utilities/numberSeq.hpp" @@ -108,6 +110,26 @@ public: virtual ~ShenandoahAdaptiveHeuristics(); + virtual void initialize() override; + + virtual void post_initialize() override; + + virtual void adjust_penalty(intx step) override; + + // At the end of GC(N), we idle GC until necessary to start the next GC. Compute the threshold of memory that can be allocated + // before we need to start the next GC. + void start_idle_span() override; + + // Having observed a new allocation rate sample, add this to the acceleration history so that we can determine if allocation + // rate is accelerating. + void add_rate_to_acceleration_history(double timestamp, double rate); + + // Compute and return the current allocation rate, the current rate of acceleration, and the amount of memory that we expect + // to consume if we start GC right now and gc takes predicted_cycle_time to complete. + size_t accelerated_consumption(double& acceleration, double& current_rate, + double avg_rate_words_per_sec, double predicted_cycle_time) const; + + void choose_collection_set_from_regiondata(ShenandoahCollectionSet* cset, RegionData* data, size_t size, size_t actual_free) override; @@ -136,6 +158,8 @@ public: const static double LOWEST_EXPECTED_AVAILABLE_AT_END; const static double HIGHEST_EXPECTED_AVAILABLE_AT_END; + const static size_t GC_TIME_SAMPLE_SIZE; + friend class ShenandoahAllocationRate; // Used to record the last trigger that signaled to start a GC. @@ -150,9 +174,19 @@ public: void adjust_margin_of_error(double amount); void adjust_spike_threshold(double amount); + // Returns number of words that can be allocated before we need to trigger next GC, given available in bytes. + inline size_t allocatable(size_t available) const { + return (available > _headroom_adjustment)? (available - _headroom_adjustment) / HeapWordSize: 0; + } + protected: ShenandoahAllocationRate _allocation_rate; + // Invocations of should_start_gc() happen approximately once per ms. Queries of allocation rate only happen if a + // a certain amount of time has passed since the previous query. + size_t _allocated_at_previous_query; + double _time_of_previous_allocation_query; + // The margin of error expressed in standard deviations to add to our // average cycle time and allocation rate. As this value increases we // tend to overestimate the rate at which mutators will deplete the @@ -179,6 +213,48 @@ protected: // source of feedback to adjust trigger parameters. TruncatedSeq _available; + ShenandoahFreeSet* _free_set; + + // This represents the time at which the allocation rate was most recently sampled for the purpose of detecting acceleration. + double _previous_acceleration_sample_timestamp; + size_t _total_allocations_at_start_of_idle; + + // bytes of headroom at which we should trigger GC + size_t _headroom_adjustment; + + // Keep track of GC_TIME_SAMPLE_SIZE most recent concurrent GC cycle times + uint _gc_time_first_sample_index; + uint _gc_time_num_samples; + double* const _gc_time_timestamps; + double* const _gc_time_samples; + double* const _gc_time_xy; // timestamp * sample + double* const _gc_time_xx; // timestamp squared + double _gc_time_sum_of_timestamps; + double _gc_time_sum_of_samples; + double _gc_time_sum_of_xy; + double _gc_time_sum_of_xx; + + double _gc_time_m; // slope + double _gc_time_b; // y-intercept + double _gc_time_sd; // sd on deviance from prediction + + // In preparation for a span during which GC will be idle, compute the headroom adjustment that will be used to + // detect when GC needs to trigger. + void compute_headroom_adjustment() override; + + void add_gc_time(double timestamp_at_start, double duration); + void add_degenerated_gc_time(double timestamp_at_start, double duration); + double predict_gc_time(double timestamp_at_start); + + // Keep track of SPIKE_ACCELERATION_SAMPLE_SIZE most recent spike allocation rate measurements. Note that it is + // typical to experience a small spike following end of GC cycle, as mutator threads refresh their TLABs. But + // there is generally an abundance of memory at this time as well, so this will not generally trigger GC. + uint _spike_acceleration_buffer_size; + uint _spike_acceleration_first_sample_index; + uint _spike_acceleration_num_samples; + double* const _spike_acceleration_rate_samples; // holds rates in words/second + double* const _spike_acceleration_rate_timestamps; + // A conservative minimum threshold of free space that we'll try to maintain when possible. // For example, we might trigger a concurrent gc if we are likely to drop below // this threshold, or we might consider this when dynamically resizing generations diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index 029b917deab..f3d31b8d0e1 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -52,6 +52,12 @@ static int compare_by_aged_live(AgedRegionData a, AgedRegionData b) { return 0; } +void ShenandoahGenerationalHeuristics::post_initialize() { + ShenandoahHeuristics::post_initialize(); + _free_set = ShenandoahHeap::heap()->free_set(); + compute_headroom_adjustment(); +} + inline void assert_no_in_place_promotions() { #ifdef ASSERT class ShenandoahNoInPlacePromotions : public ShenandoahHeapRegionClosure { diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp index 74d657feab7..da883d0d26f 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp @@ -49,6 +49,8 @@ public: void choose_collection_set(ShenandoahCollectionSet* collection_set) override; + virtual void post_initialize() override; + private: // Compute evacuation budgets prior to choosing collection set. void compute_evacuation_budgets(ShenandoahHeap* const heap); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp index 8fc744112bf..603e00c401d 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp @@ -46,13 +46,16 @@ int ShenandoahHeuristics::compare_by_garbage(RegionData a, RegionData b) { } ShenandoahHeuristics::ShenandoahHeuristics(ShenandoahSpaceInfo* space_info) : + _most_recent_trigger_evaluation_time(os::elapsedTime()), + _most_recent_planned_sleep_interval(0.0), _start_gc_is_pending(false), _declined_trigger_count(0), _most_recent_declined_trigger_count(0), _space_info(space_info), _region_data(nullptr), _guaranteed_gc_interval(0), - _cycle_start(os::elapsedTime()), + _precursor_cycle_start(os::elapsedTime()), + _cycle_start(_precursor_cycle_start), _last_cycle_end(0), _gc_times_learned(0), _gc_time_penalties(0), @@ -156,6 +159,19 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec collection_set->summarize(total_garbage, immediate_garbage, immediate_regions); } +void ShenandoahHeuristics::start_idle_span() { + // do nothing +} + +void ShenandoahHeuristics::record_degenerated_cycle_start(bool out_of_cycle) { + if (out_of_cycle) { + _precursor_cycle_start = _cycle_start = os::elapsedTime(); + } else { + _precursor_cycle_start = _cycle_start; + _cycle_start = os::elapsedTime(); + } +} + void ShenandoahHeuristics::record_cycle_start() { _cycle_start = os::elapsedTime(); } @@ -197,7 +213,6 @@ bool ShenandoahHeuristics::should_degenerate_cycle() { void ShenandoahHeuristics::adjust_penalty(intx step) { assert(0 <= _gc_time_penalties && _gc_time_penalties <= 100, "In range before adjustment: %zd", _gc_time_penalties); - if ((_most_recent_declined_trigger_count <= Penalty_Free_Declinations) && (step > 0)) { // Don't penalize if heuristics are not responsible for a negative outcome. Allow Penalty_Free_Declinations following // previous GC for self calibration without penalty. @@ -274,6 +289,17 @@ void ShenandoahHeuristics::initialize() { // Nothing to do by default. } +void ShenandoahHeuristics::post_initialize() { + // Nothing to do by default. +} + double ShenandoahHeuristics::elapsed_cycle_time() const { return os::elapsedTime() - _cycle_start; } + + +// Includes the time spent in abandoned concurrent GC cycle that may have triggered this degenerated cycle. +double ShenandoahHeuristics::elapsed_degenerated_cycle_time() const { + double now = os::elapsedTime(); + return now - _precursor_cycle_start; +} diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp index 633c4e87126..5bfba4f52d5 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp @@ -78,6 +78,10 @@ class ShenandoahHeuristics : public CHeapObj { }; #endif +private: + double _most_recent_trigger_evaluation_time; + double _most_recent_planned_sleep_interval; + protected: static const uint Moving_Average_Samples = 10; // Number of samples to store in moving averages @@ -85,14 +89,13 @@ protected: size_t _declined_trigger_count; // This counts how many times since previous GC finished that this // heuristic has answered false to should_start_gc(). size_t _most_recent_declined_trigger_count; - ; // This represents the value of _declined_trigger_count as captured at the + // This represents the value of _declined_trigger_count as captured at the // moment the most recent GC effort was triggered. In case the most recent // concurrent GC effort degenerates, the value of this variable allows us to // differentiate between degeneration because heuristic was overly optimistic // in delaying the trigger vs. degeneration for other reasons (such as the // most recent GC triggered "immediately" after previous GC finished, but the // free headroom has already been depleted). - class RegionData { private: ShenandoahHeapRegion* _region; @@ -103,6 +106,7 @@ protected: #ifdef ASSERT UnionTag _union_tag; #endif + public: inline void clear() { @@ -171,6 +175,7 @@ protected: size_t _guaranteed_gc_interval; + double _precursor_cycle_start; double _cycle_start; double _last_cycle_end; @@ -188,7 +193,7 @@ protected: RegionData* data, size_t data_size, size_t free) = 0; - void adjust_penalty(intx step); + virtual void adjust_penalty(intx step); inline void accept_trigger() { _most_recent_declined_trigger_count = _declined_trigger_count; @@ -200,6 +205,14 @@ protected: _declined_trigger_count++; } + inline double get_most_recent_wake_time() const { + return _most_recent_trigger_evaluation_time; + } + + inline double get_planned_sleep_interval() const { + return _most_recent_planned_sleep_interval; + } + public: ShenandoahHeuristics(ShenandoahSpaceInfo* space_info); virtual ~ShenandoahHeuristics(); @@ -212,10 +225,22 @@ public: _guaranteed_gc_interval = guaranteed_gc_interval; } + virtual void start_idle_span(); + virtual void compute_headroom_adjustment() { + // Default implementation does nothing. + } + virtual void record_cycle_start(); + void record_degenerated_cycle_start(bool out_of_cycle); + virtual void record_cycle_end(); + void update_should_start_query_times(double now, double planned_sleep_interval) { + _most_recent_trigger_evaluation_time = now; + _most_recent_planned_sleep_interval = planned_sleep_interval; + } + virtual bool should_start_gc(); inline void cancel_trigger_request() { @@ -248,8 +273,10 @@ public: virtual bool is_diagnostic() = 0; virtual bool is_experimental() = 0; virtual void initialize(); + virtual void post_initialize(); double elapsed_cycle_time() const; + double elapsed_degenerated_cycle_time() const; virtual size_t force_alloc_rate_sample(size_t bytes_allocated) { // do nothing diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp index beff2200d90..09508a1163f 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp @@ -137,6 +137,7 @@ bool ShenandoahYoungHeuristics::should_start_gc() { // inherited triggers have already decided to start a cycle, so no further evaluation is required if (ShenandoahAdaptiveHeuristics::should_start_gc()) { + // ShenandoahAdaptiveHeuristics::should_start_gc() has already accepted trigger, or declined it. return true; } @@ -178,7 +179,7 @@ size_t ShenandoahYoungHeuristics::bytes_of_allocation_runway_before_gc_trigger(s size_t capacity = _space_info->max_capacity(); size_t usage = _space_info->used(); size_t available = (capacity > usage)? capacity - usage: 0; - size_t allocated = _space_info->bytes_allocated_since_gc_start(); + size_t allocated = _free_set->get_bytes_allocated_since_gc_start(); size_t available_young_collected = ShenandoahHeap::heap()->collection_set()->get_young_available_bytes_collected(); size_t anticipated_available = diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 5206a0558e8..f0125c38cae 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -1215,6 +1215,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() { } heap->rebuild_free_set(true /*concurrent*/); + _generation->heuristics()->start_idle_span(); { ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index bc11659c5e5..c5607421265 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -59,6 +59,7 @@ void ShenandoahControlThread::run_service() { ShenandoahCollectorPolicy* const policy = heap->shenandoah_policy(); ShenandoahHeuristics* const heuristics = heap->heuristics(); + double most_recent_wake_time = os::elapsedTime(); while (!should_terminate()) { const GCCause::Cause cancelled_cause = heap->cancelled_cause(); if (cancelled_cause == GCCause::_shenandoah_stop_vm) { @@ -222,16 +223,26 @@ void ShenandoahControlThread::run_service() { // Wait before performing the next action. If allocation happened during this wait, // we exit sooner, to let heuristics re-evaluate new conditions. If we are at idle, // back off exponentially. - const double current = os::elapsedTime(); + const double before_sleep = most_recent_wake_time; if (heap->has_changed()) { sleep = ShenandoahControlIntervalMin; - } else if ((current - last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ + } else if ((before_sleep - last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ sleep = MIN2(ShenandoahControlIntervalMax, MAX2(1, sleep * 2)); - last_sleep_adjust_time = current; + last_sleep_adjust_time = before_sleep; } - MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); ml.wait(sleep); + // Record a conservative estimate of the longest anticipated sleep duration until we sample again. + double planned_sleep_interval = MIN2(ShenandoahControlIntervalMax, MAX2(1, sleep * 2)) / 1000.0; + most_recent_wake_time = os::elapsedTime(); + heuristics->update_should_start_query_times(most_recent_wake_time, planned_sleep_interval); + if (LogTarget(Debug, gc, thread)::is_enabled()) { + double elapsed = most_recent_wake_time - before_sleep; + double hiccup = elapsed - double(sleep); + if (hiccup > 0.001) { + log_debug(gc, thread)("Control Thread hiccup time: %.3fs", hiccup); + } + } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index 99776e38bfe..8cd8a390c4a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -314,6 +314,7 @@ void ShenandoahDegenGC::op_degenerated() { if (progress) { heap->notify_gc_progress(); _generation->heuristics()->record_degenerated(); + heap->start_idle_span(); } else if (policy->should_upgrade_degenerated_gc()) { // Upgrade to full GC, register full-GC impact on heuristics. op_degenerated_futile(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 961800f20d9..c39e2e7bb79 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -287,9 +287,25 @@ void ShenandoahFreeSet::resize_old_collector_capacity(size_t regions) { // else, old generation is already appropriately sized } + void ShenandoahFreeSet::reset_bytes_allocated_since_gc_start(size_t initial_bytes_allocated) { shenandoah_assert_heaplocked(); + // Future inquiries of get_total_bytes_allocated() will return the sum of + // _total_bytes_previously_allocated and _mutator_bytes_allocated_since_gc_start. + // Since _mutator_bytes_allocated_since_gc_start does not start at zero, we subtract initial_bytes_allocated so as + // to not double count these allocated bytes. + size_t original_mutator_bytes_allocated_since_gc_start = _mutator_bytes_allocated_since_gc_start; + + // Setting _mutator_bytes_allocated_since_gc_start before _total_bytes_previously_allocated reduces the damage + // in the case that the control or regulator thread queries get_bytes_allocated_since_previous_sample() between + // the two assignments. + // + // These are not declared as volatile so the compiler or hardware may reorder the assignments. The implementation of + // get_bytes_allocated_since_previous_cycle() is robust to this possibility, as are triggering heuristics. The current + // implementation assumes we are better off to tolerate the very rare race rather than impose a synchronization penalty + // on every update and fetch. (Perhaps it would be better to make the opposite tradeoff for improved maintainability.) _mutator_bytes_allocated_since_gc_start = initial_bytes_allocated; + _total_bytes_previously_allocated += original_mutator_bytes_allocated_since_gc_start - initial_bytes_allocated; } void ShenandoahFreeSet::increase_bytes_allocated(size_t bytes) { @@ -1211,6 +1227,8 @@ inline void ShenandoahRegionPartitions::assert_bounds_sanity() { ShenandoahFreeSet::ShenandoahFreeSet(ShenandoahHeap* heap, size_t max_regions) : _heap(heap), _partitions(max_regions, this), + _total_bytes_previously_allocated(0), + _mutator_bytes_at_last_sample(0), _total_humongous_waste(0), _alloc_bias_weight(0), _total_young_used(0), @@ -1676,9 +1694,6 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah // Regardless of whether this allocation succeeded, if the remaining memory is less than PLAB:min_size(), retire this region. // Note that retire_from_partition() increases used to account for waste. - // Also, if this allocation request failed and the consumed within this region * ShenandoahEvacWaste > region size, - // then retire the region so that subsequent searches can find available memory more quickly. - size_t idx = r->index(); size_t waste_bytes = _partitions.retire_from_partition(orig_partition, idx, r->used()); DEBUG_ONLY(boundary_changed = true;) @@ -1796,7 +1811,6 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req, bo // found the match break; } - end++; } @@ -2036,7 +2050,8 @@ void ShenandoahFreeSet::clear_internal() { _partitions.set_bias_from_left_to_right(ShenandoahFreeSetPartitionId::OldCollector, false); } -void ShenandoahFreeSet::find_regions_with_alloc_capacity(size_t &young_trashed_regions, size_t &old_trashed_regions, +// Returns total allocatable words in Mutator partition +size_t ShenandoahFreeSet::find_regions_with_alloc_capacity(size_t &young_trashed_regions, size_t &old_trashed_regions, size_t &first_old_region, size_t &last_old_region, size_t &old_region_count) { // This resets all state information, removing all regions from all sets. @@ -2054,6 +2069,8 @@ void ShenandoahFreeSet::find_regions_with_alloc_capacity(size_t &young_trashed_r size_t region_size_bytes = _partitions.region_size_bytes(); size_t max_regions = _partitions.max(); + size_t mutator_alloc_capacity_in_words = 0; + size_t mutator_leftmost = max_regions; size_t mutator_rightmost = 0; size_t mutator_leftmost_empty = max_regions; @@ -2123,6 +2140,7 @@ void ShenandoahFreeSet::find_regions_with_alloc_capacity(size_t &young_trashed_r if (region->is_trash() || !region->is_old()) { // Both young and old (possibly immediately) collected regions (trashed) are placed into the Mutator set _partitions.raw_assign_membership(idx, ShenandoahFreeSetPartitionId::Mutator); + mutator_alloc_capacity_in_words += ac / HeapWordSize; if (idx < mutator_leftmost) { mutator_leftmost = idx; } @@ -2279,6 +2297,7 @@ void ShenandoahFreeSet::find_regions_with_alloc_capacity(size_t &young_trashed_r _partitions.rightmost(ShenandoahFreeSetPartitionId::Mutator), _partitions.leftmost(ShenandoahFreeSetPartitionId::OldCollector), _partitions.rightmost(ShenandoahFreeSetPartitionId::OldCollector)); + return mutator_alloc_capacity_in_words; } void ShenandoahFreeSet::transfer_humongous_regions_from_mutator_to_old_collector(size_t xfer_regions, @@ -2583,19 +2602,20 @@ void ShenandoahFreeSet::prepare_to_rebuild(size_t &young_trashed_regions, size_t clear(); log_debug(gc, free)("Rebuilding FreeSet"); - // This places regions that have alloc_capacity into the old_collector set if they identify as is_old() or the - // mutator set otherwise. All trashed (cset) regions are affiliated young and placed in mutator set. - find_regions_with_alloc_capacity(young_trashed_regions, old_trashed_regions, - first_old_region, last_old_region, old_region_count); + // Place regions that have alloc_capacity into the old_collector set if they identify as is_old() or the + // mutator set otherwise. All trashed (cset) regions are affiliated young and placed in mutator set. Save the + // allocatable words in mutator partition in state variable. + _prepare_to_rebuild_mutator_free = find_regions_with_alloc_capacity(young_trashed_regions, old_trashed_regions, + first_old_region, last_old_region, old_region_count); } - -void ShenandoahFreeSet::finish_rebuild(size_t young_cset_regions, size_t old_cset_regions, size_t old_region_count) { +// Return mutator free +void ShenandoahFreeSet::finish_rebuild(size_t young_trashed_regions, size_t old_trashed_regions, size_t old_region_count) { shenandoah_assert_heaplocked(); size_t young_reserve(0), old_reserve(0); if (_heap->mode()->is_generational()) { - compute_young_and_old_reserves(young_cset_regions, old_cset_regions, young_reserve, old_reserve); + compute_young_and_old_reserves(young_trashed_regions, old_trashed_regions, young_reserve, old_reserve); } else { young_reserve = (_heap->max_capacity() / 100) * ShenandoahEvacReserve; old_reserve = 0; @@ -2744,10 +2764,13 @@ void ShenandoahFreeSet::compute_young_and_old_reserves(size_t young_trashed_regi // into the collector set or old collector set in order to assure that the memory available for allocations within // the collector set is at least to_reserve and the memory available for allocations within the old collector set // is at least to_reserve_old. -void ShenandoahFreeSet::reserve_regions(size_t to_reserve, size_t to_reserve_old, size_t &old_region_count, - size_t &young_used_regions, size_t &old_used_regions, - size_t &young_used_bytes, size_t &old_used_bytes) { +// +// Returns total mutator alloc capacity, in words. +size_t ShenandoahFreeSet::reserve_regions(size_t to_reserve, size_t to_reserve_old, size_t &old_region_count, + size_t &young_used_regions, size_t &old_used_regions, + size_t &young_used_bytes, size_t &old_used_bytes) { const size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes(); + size_t mutator_allocatable_words = _prepare_to_rebuild_mutator_free; young_used_regions = 0; old_used_regions = 0; @@ -2825,6 +2848,8 @@ void ShenandoahFreeSet::reserve_regions(size_t to_reserve, size_t to_reserve_old _partitions.leftmost(ShenandoahFreeSetPartitionId::OldCollector), _partitions.rightmost(ShenandoahFreeSetPartitionId::OldCollector)); old_region_count++; + assert(ac = ShenandoahHeapRegion::region_size_bytes(), "Cannot move to old unless entire region is in alloc capacity"); + mutator_allocatable_words -= ShenandoahHeapRegion::region_size_words(); continue; } } @@ -2868,8 +2893,10 @@ void ShenandoahFreeSet::reserve_regions(size_t to_reserve, size_t to_reserve_old " Collector range [%zd, %zd]", _partitions.leftmost(ShenandoahFreeSetPartitionId::Mutator), _partitions.rightmost(ShenandoahFreeSetPartitionId::Mutator), - _partitions.leftmost(ShenandoahFreeSetPartitionId::Collector), - _partitions.rightmost(ShenandoahFreeSetPartitionId::Collector)); + _partitions.leftmost(ShenandoahFreeSetPartitionId::OldCollector), + _partitions.rightmost(ShenandoahFreeSetPartitionId::OldCollector)); + + mutator_allocatable_words -= ac / HeapWordSize; continue; } @@ -2977,6 +3004,7 @@ void ShenandoahFreeSet::reserve_regions(size_t to_reserve, size_t to_reserve_old PROPERFMTARGS(to_reserve), PROPERFMTARGS(reserve)); } } + return mutator_allocatable_words; } void ShenandoahFreeSet::establish_old_collector_alloc_bias() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp index d55a06d5713..2df06432bd2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp @@ -437,6 +437,12 @@ private: ShenandoahHeap* const _heap; ShenandoahRegionPartitions _partitions; + size_t _total_bytes_previously_allocated; + size_t _mutator_bytes_at_last_sample; + + // Temporarily holds mutator_Free allocatable bytes between prepare_to_rebuild() and finish_rebuild() + size_t _prepare_to_rebuild_mutator_free; + // This locks the rebuild process (in combination with the global heap lock). Whenever we rebuild the free set, // we first acquire the global heap lock and then we acquire this _rebuild_lock in a nested context. Threads that // need to check available, acquire only the _rebuild_lock to make sure that they are not obtaining the value of @@ -446,10 +452,10 @@ private: // locks will acquire them in the same order: first the global heap lock and then the rebuild lock. ShenandoahRebuildLock _rebuild_lock; - size_t _total_humongous_waste; - HeapWord* allocate_aligned_plab(size_t size, ShenandoahAllocRequest& req, ShenandoahHeapRegion* r); + size_t _total_humongous_waste; + // We re-evaluate the left-to-right allocation bias whenever _alloc_bias_weight is less than zero. Each time // we allocate an object, we decrement the count of this value. Each time we re-evaluate whether to allocate // from right-to-left or left-to-right, we reset the value of this counter to _InitialAllocBiasWeight. @@ -662,10 +668,47 @@ public: void increase_bytes_allocated(size_t bytes); + // Return an approximation of the bytes allocated since GC start. The value returned is monotonically non-decreasing + // in time within each GC cycle. For certain GC cycles, the value returned may include some bytes allocated before + // the start of the current GC cycle. inline size_t get_bytes_allocated_since_gc_start() const { return _mutator_bytes_allocated_since_gc_start; } + inline size_t get_total_bytes_allocated() { + return _mutator_bytes_allocated_since_gc_start + _total_bytes_previously_allocated; + } + + inline size_t get_bytes_allocated_since_previous_sample() { + size_t total_bytes = get_total_bytes_allocated(); + size_t result; + if (total_bytes < _mutator_bytes_at_last_sample) { + // This rare condition may occur if bytes allocated overflows (wraps around) size_t tally of allocations. + // This may also occur in the very rare situation that get_total_bytes_allocated() is queried in the middle of + // reset_bytes_allocated_since_gc_start(). Note that there is no lock to assure that the two global variables + // it modifies are modified atomically (_total_bytes_previously_allocated and _mutator_byts_allocated_since_gc_start) + // This has been observed to occur when an out-of-cycle degenerated cycle is starting (and thus calls + // reset_bytes_allocated_since_gc_start()) at the same time that the control (non-generational mode) or + // regulator (generational-mode) thread calls should_start_gc() (which invokes get_bytes_allocated_since_previous_sample()). + // + // Handle this rare situation by responding with the "innocent" value 0 and resetting internal state so that the + // the next query can recalibrate. + result = 0; + } else { + // Note: there's always the possibility that the tally of total allocations exceeds the 64-bit capacity of our size_t + // counter. We assume that the difference between relevant samples does not exceed this count. Example: + // Suppose _mutator_words_at_last_sample is 0xffff_ffff_ffff_fff0 (18,446,744,073,709,551,600 Decimal) + // and _total_words is 0x0000_0000_0000_0800 ( 32,768 Decimal) + // Then, total_words - _mutator_words_at_last_sample can be done adding 1's complement of subtrahend: + // 1's complement of _mutator_words_at_last_sample is: 0x0000_0000_0000_0010 ( 16 Decimal)) + // plus total_words: 0x0000_0000_0000_0800 (32,768 Decimal) + // sum: 0x0000_0000_0000_0810 (32,784 Decimal) + result = total_bytes - _mutator_bytes_at_last_sample; + } + _mutator_bytes_at_last_sample = total_bytes; + return result; + } + // Public because ShenandoahRegionPartitions assertions require access. inline size_t alloc_capacity(ShenandoahHeapRegion *r) const; inline size_t alloc_capacity(size_t idx) const; @@ -781,15 +824,15 @@ public: // Acquire heap lock and log status, assuming heap lock is not acquired by the caller. void log_status_under_lock(); - // Note that capacity is the number of regions that had available memory at most recent rebuild. It is not the - // entire size of the young or global generation. (Regions within the generation that were fully utilized at time of - // rebuild are not counted as part of capacity.) - - // All three of the following functions may produce stale data if called without owning the global heap lock. + // All four of the following functions may produce stale data if called without owning the global heap lock. // Changes to the values of these variables are performed with a lock. A change to capacity or used "atomically" // adjusts available with respect to lock holders. However, sequential calls to these three functions may produce // inconsistent data: available may not equal capacity - used because the intermediate states of any "atomic" // locked action can be seen by these unlocked functions. + + // Note that capacity is the number of regions that had available memory at most recent rebuild. It is not the + // entire size of the young or global generation. (Regions within the generation that were fully utilized at time of + // rebuild are not counted as part of capacity.) inline size_t capacity_holding_lock() const { shenandoah_assert_heaplocked(); return _partitions.capacity_of(ShenandoahFreeSetPartitionId::Mutator); @@ -808,11 +851,14 @@ public: ShenandoahRebuildLocker locker(rebuild_lock()); return _partitions.used_by(ShenandoahFreeSetPartitionId::Mutator); } + inline size_t reserved() const { return _partitions.capacity_of(ShenandoahFreeSetPartitionId::Collector); } inline size_t available() { shenandoah_assert_not_heaplocked(); ShenandoahRebuildLocker locker(rebuild_lock()); return _partitions.available_in_locked_for_rebuild(ShenandoahFreeSetPartitionId::Mutator); } + inline size_t available_holding_lock() const + { return _partitions.available_in(ShenandoahFreeSetPartitionId::Mutator); } // Use this version of available() if the heap lock is held. inline size_t available_locked() const { @@ -880,13 +926,17 @@ public: // first_old_region is the index of the first region that is part of the OldCollector set // last_old_region is the index of the last region that is part of the OldCollector set // old_region_count is the number of regions in the OldCollector set that have memory available to be allocated - void find_regions_with_alloc_capacity(size_t &young_cset_regions, size_t &old_cset_regions, - size_t &first_old_region, size_t &last_old_region, size_t &old_region_count); + // + // Returns allocatable memory within Mutator partition, in words. + size_t find_regions_with_alloc_capacity(size_t &young_cset_regions, size_t &old_cset_regions, + size_t &first_old_region, size_t &last_old_region, size_t &old_region_count); // Ensure that Collector has at least to_reserve bytes of available memory, and OldCollector has at least old_reserve // bytes of available memory. On input, old_region_count holds the number of regions already present in the // OldCollector partition. Upon return, old_region_count holds the updated number of regions in the OldCollector partition. - void reserve_regions(size_t to_reserve, size_t old_reserve, size_t &old_region_count, + // + // Returns allocatable memory within Mutator partition, in words. + size_t reserve_regions(size_t to_reserve, size_t old_reserve, size_t &old_region_count, size_t &young_used_regions, size_t &old_used_regions, size_t &young_used_bytes, size_t &old_used_bytes); // Reserve space for evacuations, with regions reserved for old evacuations placed to the right diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index 3c92750cc0c..750f7e9122d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -252,6 +252,7 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { phase5_epilog(); } + heap->start_idle_span(); // Resize metaspace MetaspaceGC::compute_new_size(); @@ -1124,8 +1125,9 @@ void ShenandoahFullGC::phase5_epilog() { if (heap->mode()->is_generational()) { ShenandoahGenerationalFullGC::compute_balances(); } - free_set->finish_rebuild(young_trashed_regions, old_trashed_regions, num_old); + heap->free_set()->finish_rebuild(young_trashed_regions, old_trashed_regions, num_old); } + // Set mark incomplete because the marking bitmaps have been reset except pinned regions. _generation->set_mark_incomplete(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index ddb50ee0020..b2d5e5423dd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -151,6 +151,10 @@ ShenandoahHeuristics* ShenandoahGeneration::initialize_heuristics(ShenandoahMode return _heuristics; } +void ShenandoahGeneration::post_initialize_heuristics() { + _heuristics->post_initialize(); +} + void ShenandoahGeneration::set_evacuation_reserve(size_t new_val) { shenandoah_assert_heaplocked(); _evacuation_reserve = new_val; @@ -358,8 +362,7 @@ void ShenandoahGeneration::cancel_marking() { set_concurrent_mark_in_progress(false); } -ShenandoahGeneration::ShenandoahGeneration(ShenandoahGenerationType type, - uint max_workers) : +ShenandoahGeneration::ShenandoahGeneration(ShenandoahGenerationType type, uint max_workers) : _type(type), _task_queues(new ShenandoahObjToScanQueueSet(max_workers)), _ref_processor(new ShenandoahReferenceProcessor(this, MAX2(max_workers, 1U))), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 946f2b91520..1a549be8988 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -83,10 +83,10 @@ private: ShenandoahReferenceProcessor* ref_processor() { return _ref_processor; } virtual ShenandoahHeuristics* initialize_heuristics(ShenandoahMode* gc_mode); + virtual void post_initialize_heuristics(); virtual void post_initialize(ShenandoahHeap* heap); - virtual size_t bytes_allocated_since_gc_start() const override = 0; virtual size_t used() const override = 0; virtual size_t used_regions() const = 0; virtual size_t used_regions_size() const = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 3b57190cc75..cc7547b8ac1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -622,10 +622,11 @@ void ShenandoahGenerationalControlThread::service_stw_full_cycle(GCCause::Cause void ShenandoahGenerationalControlThread::service_stw_degenerated_cycle(const ShenandoahGCRequest& request) { assert(_degen_point != ShenandoahGC::_degenerated_unset, "Degenerated point should be set"); + request.generation->heuristics()->record_degenerated_cycle_start(ShenandoahGC::ShenandoahDegenPoint::_degenerated_outside_cycle + == _degen_point); _heap->increment_total_collections(false); ShenandoahGCSession session(request.cause, request.generation); - ShenandoahDegenGC gc(_degen_point, request.generation); gc.collect(request.cause); _degen_point = ShenandoahGC::_degenerated_unset; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 2c2e5533c01..b302bde8510 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -90,11 +90,23 @@ ShenandoahGenerationalHeap::ShenandoahGenerationalHeap(ShenandoahCollectorPolicy assert(is_aligned(_max_plab_size, CardTable::card_size_in_words()), "max_plab_size must be aligned"); } +void ShenandoahGenerationalHeap::initialize_generations() { + ShenandoahHeap::initialize_generations(); + _young_generation->post_initialize(this); + _old_generation->post_initialize(this); +} + void ShenandoahGenerationalHeap::post_initialize() { ShenandoahHeap::post_initialize(); _age_census = new ShenandoahAgeCensus(); } +void ShenandoahGenerationalHeap::post_initialize_heuristics() { + ShenandoahHeap::post_initialize_heuristics(); + _young_generation->post_initialize_heuristics(); + _old_generation->post_initialize_heuristics(); +} + void ShenandoahGenerationalHeap::print_init_logger() const { ShenandoahGenerationalInitLogger logger; logger.print_all(); @@ -110,12 +122,6 @@ void ShenandoahGenerationalHeap::initialize_heuristics() { _old_generation->initialize_heuristics(mode()); } -void ShenandoahGenerationalHeap::post_initialize_heuristics() { - ShenandoahHeap::post_initialize_heuristics(); - _young_generation->post_initialize(this); - _old_generation->post_initialize(this); -} - void ShenandoahGenerationalHeap::initialize_serviceability() { assert(mode()->is_generational(), "Only for the generational mode"); _young_gen_memory_pool = new ShenandoahYoungGenMemoryPool(this); @@ -152,6 +158,10 @@ void ShenandoahGenerationalHeap::stop() { regulator_thread()->stop(); } +void ShenandoahGenerationalHeap::start_idle_span() { + young_generation()->heuristics()->start_idle_span(); +} + bool ShenandoahGenerationalHeap::requires_barriers(stackChunkOop obj) const { if (is_idle()) { return false; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index 719bae52a83..7fe0362aa3f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -40,6 +40,7 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { public: explicit ShenandoahGenerationalHeap(ShenandoahCollectorPolicy* policy); void post_initialize() override; + void initialize_generations() override; void initialize_heuristics() override; void post_initialize_heuristics() override; @@ -82,6 +83,8 @@ public: inline bool is_tenurable(const ShenandoahHeapRegion* r) const; + void start_idle_span() override; + // Ages regions that haven't been used for allocations in the current cycle. // Resets ages for regions that have been used for allocations. void update_region_ages(ShenandoahMarkingContext* ctx); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index d78bdae6a51..c6889351161 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -435,7 +435,7 @@ jint ShenandoahHeap::initialize() { } _free_set = new ShenandoahFreeSet(this, _num_regions); - post_initialize_heuristics(); + initialize_generations(); // We are initializing free set. We ignore cset region tallies. size_t young_trashed_regions, old_trashed_regions, first_old, last_old, num_old; @@ -492,16 +492,17 @@ jint ShenandoahHeap::initialize() { _phase_timings = new ShenandoahPhaseTimings(max_workers()); ShenandoahCodeRoots::initialize(); + // Initialization of controller makes use of variables established by initialize_heuristics. initialize_controller(); + // Certain initialization of heuristics must be deferred until after controller is initialized. + post_initialize_heuristics(); + start_idle_span(); if (ShenandoahUncommit) { _uncommit_thread = new ShenandoahUncommitThread(this); } - print_init_logger(); - FullGCForwarding::initialize(_heap_region); - return JNI_OK; } @@ -545,10 +546,6 @@ void ShenandoahHeap::initialize_heuristics() { _global_generation->initialize_heuristics(mode()); } -void ShenandoahHeap::post_initialize_heuristics() { - _global_generation->post_initialize(this); -} - #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable:4355 ) // 'this' : used in base member initializer list @@ -690,6 +687,11 @@ public: } }; +void ShenandoahHeap::initialize_generations() { + _global_generation->post_initialize(this); +} + +// We do not call this explicitly It is called by Hotspot infrastructure. void ShenandoahHeap::post_initialize() { CollectedHeap::post_initialize(); @@ -717,6 +719,10 @@ void ShenandoahHeap::post_initialize() { JFR_ONLY(ShenandoahJFRSupport::register_jfr_type_serializers();) } +void ShenandoahHeap::post_initialize_heuristics() { + _global_generation->post_initialize_heuristics(); +} + ShenandoahHeuristics* ShenandoahHeap::heuristics() { return _global_generation->heuristics(); } @@ -760,6 +766,7 @@ void ShenandoahHeap::set_soft_max_capacity(size_t v) { "Should be in bounds: %zu <= %zu <= %zu", min_capacity(), v, max_capacity()); _soft_max_size.store_relaxed(v); + heuristics()->compute_headroom_adjustment(); } size_t ShenandoahHeap::min_capacity() const { @@ -835,6 +842,10 @@ void ShenandoahHeap::notify_heap_changed() { _heap_changed.try_set(); } +void ShenandoahHeap::start_idle_span() { + heuristics()->start_idle_span(); +} + void ShenandoahHeap::set_forced_counters_update(bool value) { monitoring_support()->set_forced_counters_update(value); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 85ad339469d..d4604be0aec 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -195,6 +195,7 @@ public: ShenandoahHeap(ShenandoahCollectorPolicy* policy); jint initialize() override; void post_initialize() override; + virtual void initialize_generations(); void initialize_mode(); virtual void initialize_heuristics(); virtual void post_initialize_heuristics(); @@ -393,6 +394,8 @@ public: return _heap_changed.try_unset(); } + virtual void start_idle_span(); + void set_concurrent_young_mark_in_progress(bool in_progress); void set_concurrent_old_mark_in_progress(bool in_progress); void set_evacuation_in_progress(bool in_progress); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index 4fda65b4030..1b12909bcaf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -422,6 +422,7 @@ void ShenandoahOldGeneration::prepare_regions_and_collection_set(bool concurrent // At the end of old-gen, we may find that we have reclaimed immediate garbage, allowing a longer allocation runway. // We may also find that we have accumulated canddiate regions for mixed evacuation. If so, we will want to expand // the OldCollector reserve in order to make room for these mixed evacuations. + assert(ShenandoahHeap::heap()->mode()->is_generational(), "sanity"); assert(young_trash_regions == 0, "sanity"); ShenandoahGenerationalHeap* gen_heap = ShenandoahGenerationalHeap::heap(); @@ -765,6 +766,7 @@ size_t ShenandoahOldGeneration::used_regions_size() const { return used_regions * ShenandoahHeapRegion::region_size_bytes(); } +// For the old generation, max_capacity() equals soft_max_capacity() size_t ShenandoahOldGeneration::max_capacity() const { size_t total_regions = _free_set->total_old_regions(); return total_regions * ShenandoahHeapRegion::region_size_bytes(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp index ec4b7c7217c..fe92a3a3e08 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp @@ -36,7 +36,8 @@ ShenandoahRegulatorThread::ShenandoahRegulatorThread(ShenandoahGenerationalContr _heap(ShenandoahHeap::heap()), _control_thread(control_thread), _sleep(ShenandoahControlIntervalMin), - _last_sleep_adjust_time(os::elapsedTime()) { + _most_recent_wake_time(os::elapsedTime()), + _last_sleep_adjust_time(_most_recent_wake_time) { shenandoah_assert_generational(); _old_heuristics = _heap->old_generation()->heuristics(); _young_heuristics = _heap->young_generation()->heuristics(); @@ -115,19 +116,22 @@ void ShenandoahRegulatorThread::regulator_sleep() { // Wait before performing the next action. If allocation happened during this wait, // we exit sooner, to let heuristics re-evaluate new conditions. If we are at idle, // back off exponentially. - double current = os::elapsedTime(); - + double before_sleep_time = _most_recent_wake_time; if (ShenandoahHeap::heap()->has_changed()) { _sleep = ShenandoahControlIntervalMin; - } else if ((current - _last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ + } else if ((before_sleep_time - _last_sleep_adjust_time) * 1000 > ShenandoahControlIntervalAdjustPeriod){ _sleep = MIN2(ShenandoahControlIntervalMax, MAX2(1u, _sleep * 2)); - _last_sleep_adjust_time = current; + _last_sleep_adjust_time = before_sleep_time; } SuspendibleThreadSetLeaver leaver; os::naked_short_sleep(_sleep); + double wake_time = os::elapsedTime(); + _most_recent_period = wake_time - _most_recent_wake_time; + _most_recent_wake_time = wake_time; + _young_heuristics->update_should_start_query_times(_most_recent_wake_time, double(_sleep) / 1000.0); if (LogTarget(Debug, gc, thread)::is_enabled()) { - double elapsed = os::elapsedTime() - current; + double elapsed = _most_recent_wake_time - before_sleep_time; double hiccup = elapsed - double(_sleep); if (hiccup > 0.001) { log_debug(gc, thread)("Regulator hiccup time: %.3fs", hiccup); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp index 2519025b6fb..cc41bc2c65b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp @@ -79,7 +79,10 @@ class ShenandoahRegulatorThread: public ConcurrentGCThread { ShenandoahOldHeuristics* _old_heuristics; ShenandoahHeuristics* _global_heuristics; + // duration of planned regulator sleep period, in ms uint _sleep; + double _most_recent_wake_time; + double _most_recent_period; double _last_sleep_adjust_time; }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index 3eb1a06a911..d3e9a1f9fae 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -34,6 +34,59 @@ range, \ constraint) \ \ + product(uint, ShenandoahAccelerationSamplePeriod, 15, EXPERIMENTAL, \ + "When at least this much time (measured in ms) has passed " \ + "since the acceleration allocation rate was most recently " \ + "sampled, capture another allocation rate sample for the purpose "\ + "of detecting acceleration or momentary spikes in allocation " \ + "rate. A smaller value allows quicker response to changes in " \ + "allocation rates but is more vulnerable to noise and requires " \ + "more monitoring effort.") \ + range(1, 1000) \ + \ + product(uint, ShenandoahRateAccelerationSampleSize, 8, EXPERIMENTAL, \ + "In selected ShenandoahControlIntervals " \ + "(if ShenandoahAccelerationSamplePeriod ms have passed " \ + "since previous allocation rate sample), " \ + "we compute the allocation rate since the previous rate was " \ + "sampled. This many samples are analyzed to determine whether " \ + "allocation rates are accelerating. Acceleration may occur " \ + "due to increasing client demand or due to phase changes in " \ + "an application. A larger value reduces sensitivity to " \ + "noise and delays recognition of the accelerating trend. A " \ + "larger value may also cause the heuristic to miss detection " \ + "of very quick accelerations. Smaller values may cause random " \ + "noise to be perceived as acceleration of allocation rate, " \ + "triggering excess collections. Note that the acceleration " \ + "need not last the entire span of the sampled duration to be " \ + "detected. If the last several of all samples are signficantly " \ + "larger than the other samples, the best fit line through all " \ + "sampled values will have an upward slope, manifesting as " \ + "acceleration.") \ + range(1,64) \ + \ + product(uint, ShenandoahMomentaryAllocationRateSpikeSampleSize, \ + 2, EXPERIMENTAL, \ + "In selected ShenandoahControlIntervals " \ + "(if ShenandoahAccelerationSamplePeriod ms have passed " \ + "since previous allocation rate sample), we compute " \ + "the allocation rate since the previous rate was sampled. " \ + "The weighted average of this " \ + "many most recent momentary allocation rate samples is compared " \ + "against current allocation runway and anticipated GC time to " \ + "determine whether a spike in momentary allocation rate " \ + "justifies an early GC trigger. Momentary allocation spike " \ + "detection is in addition to previously implemented " \ + "ShenandoahAdaptiveInitialSpikeThreshold, the latter of which " \ + "is more effective at detecting slower spikes. The latter " \ + "spike detection samples at the rate specifieid by " \ + "ShenandoahAdaptiveSampleFrequencyHz. The value of this " \ + "parameter must be less than the value of " \ + "ShenandoahRateAccelerationSampleSize. A larger value makes " \ + "momentary spike detection less sensitive. A smaller value " \ + "may result in excessive GC triggers.") \ + range(1,64) \ + \ product(uintx, ShenandoahGenerationalMinPIPUsage, 30, EXPERIMENTAL, \ "(Generational mode only) What percent of a heap region " \ "should be used before we consider promoting a region in " \ From 297812eec1ad5c9f48822ace2bd720fd02c6b263 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 3 Mar 2026 09:54:54 +0000 Subject: [PATCH 024/170] 8378867: jpackage references non-existing "message.app-image-requires-identifier" l10n key Reviewed-by: almatvee --- .../internal/MacApplicationBuilder.java | 9 +++--- .../resources/MacResources.properties | 2 ++ .../cli/OptionsValidationFailTest.excludes | 1 + test/jdk/tools/jpackage/share/ErrorTest.java | 31 ++++++++++++++++++- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java index a73a6152f6d..43590fb5e2c 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java @@ -32,7 +32,6 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import jdk.jpackage.internal.util.RootedPath; import java.util.stream.Stream; import jdk.jpackage.internal.model.AppImageLayout; import jdk.jpackage.internal.model.AppImageSigningConfig; @@ -40,6 +39,8 @@ import jdk.jpackage.internal.model.Application; import jdk.jpackage.internal.model.Launcher; import jdk.jpackage.internal.model.MacApplication; import jdk.jpackage.internal.model.MacApplicationMixin; +import jdk.jpackage.internal.model.JPackageException; +import jdk.jpackage.internal.util.RootedPath; final class MacApplicationBuilder { @@ -183,10 +184,8 @@ final class MacApplicationBuilder { } catch (IOException ex) { throw new UncheckedIOException(ex); } catch (Exception ex) { - throw I18N.buildConfigException("message.app-image-requires-identifier") - .advice("message.app-image-requires-identifier.advice") - .cause(ex) - .create(); + throw new JPackageException( + I18N.format("error.invalid-app-image-plist-file", externalInfoPlistFile), ex); } } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties index e43cadc5782..3aebdc39d41 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties @@ -31,6 +31,8 @@ error.app-image.mac-sign.required=--mac-sign option is required with predefined error.invalid-runtime-image-missing-file=Runtime image "{0}" is missing "{1}" file error.invalid-runtime-image-bin-dir=Runtime image "{0}" should not contain "bin" folder error.invalid-runtime-image-bin-dir.advice=Use --strip-native-commands jlink option when generating runtime image used with {0} option +error.invalid-app-image-plist-file=Invalid "{0}" file in the predefined application image + resource.app-info-plist=Application Info.plist resource.app-runtime-info-plist=Embedded Java Runtime Info.plist resource.runtime-info-plist=Java Runtime Info.plist diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes index 0b98c051238..f86fb9a3897 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes @@ -23,6 +23,7 @@ ErrorTest.test(NATIVE; app-desc=Hello; args-add=[--mac-app-store, --runtime-imag ErrorTest.test(NATIVE; app-desc=Hello; args-add=[--runtime-image, @@EMPTY_DIR@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@EMPTY_DIR@@, lib/**/libjli.dylib]]) ErrorTest.test(NATIVE; app-desc=Hello; args-add=[--runtime-image, @@INVALID_MAC_RUNTIME_BUNDLE@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@INVALID_MAC_RUNTIME_BUNDLE@@, Contents/Home/lib/**/libjli.dylib]]) ErrorTest.test(NATIVE; app-desc=Hello; args-add=[--runtime-image, @@INVALID_MAC_RUNTIME_IMAGE@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@INVALID_MAC_RUNTIME_IMAGE@@, lib/**/libjli.dylib]]) +ErrorTest.test(NATIVE; args-add=[--app-image, @@MAC_APP_IMAGE_INVALID_INFO_PLIST@@]; errors=[message.error-header+[error.invalid-app-image-plist-file, @@MAC_APP_IMAGE_INVALID_INFO_PLIST@@]]) ErrorTest.test(NATIVE; args-add=[--runtime-image, @@EMPTY_DIR@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@EMPTY_DIR@@, lib/**/libjli.dylib]]) ErrorTest.test(NATIVE; args-add=[--runtime-image, @@INVALID_MAC_RUNTIME_BUNDLE@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@INVALID_MAC_RUNTIME_BUNDLE@@, Contents/Home/lib/**/libjli.dylib]]) ErrorTest.test(NATIVE; args-add=[--runtime-image, @@INVALID_MAC_RUNTIME_IMAGE@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@INVALID_MAC_RUNTIME_IMAGE@@, lib/**/libjli.dylib]]) diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index 2133823381c..8bc7ba2521f 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -26,6 +26,11 @@ import static java.util.stream.Collectors.toMap; import static jdk.internal.util.OperatingSystem.LINUX; import static jdk.internal.util.OperatingSystem.MACOS; import static jdk.internal.util.OperatingSystem.WINDOWS; +import static jdk.jpackage.internal.util.PListWriter.writeDict; +import static jdk.jpackage.internal.util.PListWriter.writePList; +import static jdk.jpackage.internal.util.XmlUtils.createXml; +import static jdk.jpackage.internal.util.XmlUtils.toXmlConsumer; +import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import static jdk.jpackage.test.JPackageCommand.makeAdvice; import static jdk.jpackage.test.JPackageCommand.makeError; @@ -46,6 +51,7 @@ import java.util.regex.Pattern; import java.util.stream.IntStream; import java.util.stream.Stream; import jdk.internal.util.OperatingSystem; +import jdk.jpackage.internal.util.MacBundle; import jdk.jpackage.internal.util.TokenReplace; import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.ParameterSupplier; @@ -54,6 +60,7 @@ import jdk.jpackage.test.CannedArgument; import jdk.jpackage.test.CannedFormattedString; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JPackageOutputValidator; +import jdk.jpackage.test.JavaTool; import jdk.jpackage.test.MacSign; import jdk.jpackage.test.MacSign.CertificateRequest; import jdk.jpackage.test.MacSign.CertificateType; @@ -105,6 +112,11 @@ public final class ErrorTest { final var appImageRoot = TKit.createTempDirectory("appimage"); final var appImageCmd = JPackageCommand.helloAppImage() + // Use the default jpackage tool provider to create an application image. + // The ErrorTest is used from the OptionsValidationFailTest unit tests that override + // the default jpackage tool provider with the implementation that doesn't do packaging + // and can not create a valid application image. + .useToolProvider(JavaTool.JPACKAGE.asToolProvider()) .setFakeRuntime().setArgumentValue("--dest", appImageRoot); appImageCmd.execute(); @@ -124,6 +136,19 @@ public final class ErrorTest { return appImageCmd.outputBundle(); }), + MAC_APP_IMAGE_INVALID_INFO_PLIST(toFunction(cmd -> { + var appImageDir = (Path)APP_IMAGE.expand(cmd).orElseThrow(); + // Replace the default Info.plist file with an empty one. + var plistFile = new MacBundle(appImageDir).infoPlistFile(); + TKit.trace(String.format("Create invalid plist file in [%s]", plistFile)); + createXml(plistFile, xml -> { + writePList(xml, toXmlConsumer(() -> { + writeDict(xml, toXmlConsumer(() -> { + })); + })); + }); + return appImageDir; + })), INVALID_MAC_RUNTIME_BUNDLE(toSupplier(() -> { // Has "Contents/MacOS/libjli.dylib", but missing "Contents/Home/lib/libjli.dylib". final Path root = TKit.createTempDirectory("mac-invalid-runtime-bundle"); @@ -963,7 +988,11 @@ public final class ErrorTest { testSpec().noAppDesc().nativeType().addArgs("--app-image", Token.EMPTY_DIR.token()) .error("error.parameter-not-mac-bundle", JPackageCommand.cannedArgument(cmd -> { return Path.of(cmd.getArgumentValue("--app-image")); - }, Token.EMPTY_DIR.token()), "--app-image") + }, Token.EMPTY_DIR.token()), "--app-image"), + testSpec().nativeType().noAppDesc().addArgs("--app-image", Token.MAC_APP_IMAGE_INVALID_INFO_PLIST.token()) + .error("error.invalid-app-image-plist-file", JPackageCommand.cannedArgument(cmd -> { + return new MacBundle(Path.of(cmd.getArgumentValue("--app-image"))).infoPlistFile(); + }, Token.MAC_APP_IMAGE_INVALID_INFO_PLIST.token())) ).map(TestSpec.Builder::create).toList()); macInvalidRuntime(testCases::add); From 57db48cc21d47475caf2d1fae6bf37eab8d7521e Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 3 Mar 2026 10:01:00 +0000 Subject: [PATCH 025/170] 8373290: Update FreeType to 2.14.1 Reviewed-by: azvegint, serb, prr --- src/java.desktop/share/legal/freetype.md | 40 +- .../include/freetype/config/ftconfig.h | 2 +- .../include/freetype/config/ftheader.h | 2 +- .../include/freetype/config/ftoption.h | 49 +- .../include/freetype/config/ftstdlib.h | 2 +- .../include/freetype/config/integer-types.h | 31 +- .../include/freetype/config/mac-support.h | 2 +- .../include/freetype/config/public-macros.h | 6 +- .../libfreetype/include/freetype/freetype.h | 98 +- .../libfreetype/include/freetype/ftadvanc.h | 2 +- .../libfreetype/include/freetype/ftbbox.h | 2 +- .../libfreetype/include/freetype/ftbdf.h | 2 +- .../libfreetype/include/freetype/ftbitmap.h | 2 +- .../libfreetype/include/freetype/ftcid.h | 2 +- .../libfreetype/include/freetype/ftcolor.h | 17 +- .../libfreetype/include/freetype/ftdriver.h | 6 +- .../libfreetype/include/freetype/fterrdef.h | 2 +- .../libfreetype/include/freetype/fterrors.h | 2 +- .../libfreetype/include/freetype/ftfntfmt.h | 2 +- .../libfreetype/include/freetype/ftgasp.h | 2 +- .../libfreetype/include/freetype/ftglyph.h | 2 +- .../libfreetype/include/freetype/ftgzip.h | 2 +- .../libfreetype/include/freetype/ftimage.h | 8 +- .../libfreetype/include/freetype/ftincrem.h | 2 +- .../libfreetype/include/freetype/ftlcdfil.h | 2 +- .../libfreetype/include/freetype/ftlist.h | 2 +- .../libfreetype/include/freetype/ftlogging.h | 2 +- .../libfreetype/include/freetype/ftmac.h | 2 +- .../libfreetype/include/freetype/ftmm.h | 256 ++- .../libfreetype/include/freetype/ftmodapi.h | 2 +- .../libfreetype/include/freetype/ftmoderr.h | 2 +- .../libfreetype/include/freetype/ftoutln.h | 2 +- .../libfreetype/include/freetype/ftparams.h | 2 +- .../libfreetype/include/freetype/ftrender.h | 2 +- .../libfreetype/include/freetype/ftsizes.h | 2 +- .../libfreetype/include/freetype/ftsnames.h | 2 +- .../libfreetype/include/freetype/ftstroke.h | 2 +- .../libfreetype/include/freetype/ftsynth.h | 2 +- .../libfreetype/include/freetype/ftsystem.h | 2 +- .../libfreetype/include/freetype/fttrigon.h | 2 +- .../libfreetype/include/freetype/fttypes.h | 2 +- .../include/freetype/internal/autohint.h | 2 +- .../include/freetype/internal/cffotypes.h | 2 +- .../include/freetype/internal/cfftypes.h | 2 +- .../freetype/internal/compiler-macros.h | 6 +- .../include/freetype/internal/ftcalc.h | 300 +-- .../include/freetype/internal/ftdebug.h | 2 +- .../include/freetype/internal/ftdrv.h | 2 +- .../include/freetype/internal/ftgloadr.h | 2 +- .../include/freetype/internal/fthash.h | 23 + .../include/freetype/internal/ftmemory.h | 2 +- .../include/freetype/internal/ftmmtypes.h | 2 +- .../include/freetype/internal/ftobjs.h | 30 +- .../include/freetype/internal/ftpsprop.h | 2 +- .../include/freetype/internal/ftrfork.h | 2 +- .../include/freetype/internal/ftserv.h | 2 +- .../include/freetype/internal/ftstream.h | 2 +- .../include/freetype/internal/fttrace.h | 5 +- .../include/freetype/internal/ftvalid.h | 2 +- .../include/freetype/internal/psaux.h | 2 +- .../include/freetype/internal/pshints.h | 2 +- .../freetype/internal/services/svbdf.h | 2 +- .../freetype/internal/services/svcfftl.h | 2 +- .../freetype/internal/services/svcid.h | 2 +- .../freetype/internal/services/svfntfmt.h | 2 +- .../freetype/internal/services/svgldict.h | 2 +- .../freetype/internal/services/svgxval.h | 2 +- .../freetype/internal/services/svkern.h | 2 +- .../freetype/internal/services/svmetric.h | 4 +- .../include/freetype/internal/services/svmm.h | 2 +- .../freetype/internal/services/svotval.h | 2 +- .../freetype/internal/services/svpfr.h | 2 +- .../freetype/internal/services/svpostnm.h | 2 +- .../freetype/internal/services/svprop.h | 2 +- .../freetype/internal/services/svpscmap.h | 2 +- .../freetype/internal/services/svpsinfo.h | 2 +- .../freetype/internal/services/svsfnt.h | 2 +- .../freetype/internal/services/svttcmap.h | 2 +- .../freetype/internal/services/svtteng.h | 2 +- .../freetype/internal/services/svttglyf.h | 2 +- .../freetype/internal/services/svwinfnt.h | 2 +- .../include/freetype/internal/sfnt.h | 8 +- .../include/freetype/internal/svginterface.h | 2 +- .../include/freetype/internal/t1types.h | 2 +- .../include/freetype/internal/tttypes.h | 41 +- .../include/freetype/internal/wofftypes.h | 2 +- .../libfreetype/include/freetype/otsvg.h | 2 +- .../libfreetype/include/freetype/t1tables.h | 2 +- .../libfreetype/include/freetype/ttnameid.h | 258 +-- .../libfreetype/include/freetype/tttables.h | 13 +- .../libfreetype/include/freetype/tttags.h | 2 +- .../native/libfreetype/include/ft2build.h | 2 +- .../native/libfreetype/src/autofit/afadjust.c | 1612 +++++++++++++++++ .../native/libfreetype/src/autofit/afadjust.h | 130 ++ .../native/libfreetype/src/autofit/afblue.c | 194 +- .../native/libfreetype/src/autofit/afblue.cin | 2 +- .../native/libfreetype/src/autofit/afblue.dat | 194 +- .../native/libfreetype/src/autofit/afblue.h | 11 +- .../native/libfreetype/src/autofit/afblue.hin | 11 +- .../native/libfreetype/src/autofit/afcjk.c | 49 +- .../native/libfreetype/src/autofit/afcjk.h | 2 +- .../native/libfreetype/src/autofit/afcover.h | 2 +- .../native/libfreetype/src/autofit/afdummy.c | 2 +- .../native/libfreetype/src/autofit/afdummy.h | 2 +- .../native/libfreetype/src/autofit/aferrors.h | 2 +- .../native/libfreetype/src/autofit/afglobal.c | 40 +- .../native/libfreetype/src/autofit/afglobal.h | 15 +- .../native/libfreetype/src/autofit/afhints.c | 23 +- .../native/libfreetype/src/autofit/afhints.h | 19 +- .../native/libfreetype/src/autofit/afindic.c | 2 +- .../native/libfreetype/src/autofit/afindic.h | 2 +- .../native/libfreetype/src/autofit/aflatin.c | 1555 +++++++++++++++- .../native/libfreetype/src/autofit/aflatin.h | 25 +- .../native/libfreetype/src/autofit/afloader.c | 2 +- .../native/libfreetype/src/autofit/afloader.h | 2 +- .../native/libfreetype/src/autofit/afmodule.c | 14 +- .../native/libfreetype/src/autofit/afmodule.h | 8 +- .../native/libfreetype/src/autofit/afranges.c | 63 +- .../native/libfreetype/src/autofit/afranges.h | 2 +- .../native/libfreetype/src/autofit/afscript.h | 2 +- .../native/libfreetype/src/autofit/afshaper.c | 340 ++-- .../native/libfreetype/src/autofit/afshaper.h | 19 +- .../native/libfreetype/src/autofit/afstyles.h | 58 +- .../native/libfreetype/src/autofit/aftypes.h | 6 +- .../libfreetype/src/autofit/afws-decl.h | 2 +- .../libfreetype/src/autofit/afws-iter.h | 2 +- .../native/libfreetype/src/autofit/ft-hb.c | 197 ++ .../native/libfreetype/src/autofit/ft-hb.h | 82 + .../native/libfreetype/src/base/ftadvanc.c | 2 +- .../native/libfreetype/src/base/ftbase.h | 4 +- .../native/libfreetype/src/base/ftbbox.c | 2 +- .../native/libfreetype/src/base/ftbitmap.c | 12 +- .../native/libfreetype/src/base/ftcalc.c | 146 +- .../share/native/libfreetype/src/base/ftcid.c | 2 +- .../native/libfreetype/src/base/ftcolor.c | 21 +- .../native/libfreetype/src/base/ftdbgmem.c | 3 +- .../native/libfreetype/src/base/ftdebug.c | 4 +- .../native/libfreetype/src/base/ftfntfmt.c | 2 +- .../native/libfreetype/src/base/ftfstype.c | 2 +- .../native/libfreetype/src/base/ftgasp.c | 2 +- .../native/libfreetype/src/base/ftgloadr.c | 2 +- .../native/libfreetype/src/base/ftglyph.c | 2 +- .../native/libfreetype/src/base/fthash.c | 104 +- .../native/libfreetype/src/base/ftinit.c | 2 +- .../native/libfreetype/src/base/ftlcdfil.c | 2 +- .../share/native/libfreetype/src/base/ftmac.c | 2 +- .../share/native/libfreetype/src/base/ftmm.c | 37 +- .../native/libfreetype/src/base/ftobjs.c | 64 +- .../native/libfreetype/src/base/ftoutln.c | 2 +- .../native/libfreetype/src/base/ftpatent.c | 2 +- .../native/libfreetype/src/base/ftpsprop.c | 2 +- .../native/libfreetype/src/base/ftrfork.c | 10 +- .../native/libfreetype/src/base/ftsnames.c | 2 +- .../native/libfreetype/src/base/ftstream.c | 4 +- .../native/libfreetype/src/base/ftstroke.c | 24 +- .../native/libfreetype/src/base/ftsynth.c | 4 +- .../native/libfreetype/src/base/ftsystem.c | 4 +- .../native/libfreetype/src/base/fttrigon.c | 2 +- .../native/libfreetype/src/base/fttype1.c | 2 +- .../native/libfreetype/src/base/ftutil.c | 2 +- .../native/libfreetype/src/cff/cffcmap.c | 2 +- .../native/libfreetype/src/cff/cffcmap.h | 2 +- .../native/libfreetype/src/cff/cffdrivr.c | 162 +- .../native/libfreetype/src/cff/cffdrivr.h | 2 +- .../native/libfreetype/src/cff/cfferrs.h | 2 +- .../native/libfreetype/src/cff/cffgload.c | 70 +- .../native/libfreetype/src/cff/cffgload.h | 2 +- .../native/libfreetype/src/cff/cffload.c | 16 +- .../native/libfreetype/src/cff/cffload.h | 2 +- .../native/libfreetype/src/cff/cffobjs.c | 16 +- .../native/libfreetype/src/cff/cffobjs.h | 2 +- .../native/libfreetype/src/cff/cffparse.c | 10 +- .../native/libfreetype/src/cff/cffparse.h | 2 +- .../native/libfreetype/src/cff/cfftoken.h | 2 +- .../native/libfreetype/src/cid/ciderrs.h | 2 +- .../native/libfreetype/src/cid/cidgload.c | 46 +- .../native/libfreetype/src/cid/cidgload.h | 2 +- .../native/libfreetype/src/cid/cidload.c | 2 +- .../native/libfreetype/src/cid/cidload.h | 2 +- .../native/libfreetype/src/cid/cidobjs.c | 2 +- .../native/libfreetype/src/cid/cidobjs.h | 2 +- .../native/libfreetype/src/cid/cidparse.c | 2 +- .../native/libfreetype/src/cid/cidparse.h | 2 +- .../native/libfreetype/src/cid/cidriver.c | 2 +- .../native/libfreetype/src/cid/cidriver.h | 2 +- .../native/libfreetype/src/cid/cidtoken.h | 2 +- .../native/libfreetype/src/psaux/afmparse.c | 2 +- .../native/libfreetype/src/psaux/afmparse.h | 2 +- .../native/libfreetype/src/psaux/cffdecode.c | 6 +- .../native/libfreetype/src/psaux/cffdecode.h | 2 +- .../native/libfreetype/src/psaux/psauxerr.h | 2 +- .../native/libfreetype/src/psaux/psauxmod.c | 2 +- .../native/libfreetype/src/psaux/psauxmod.h | 5 +- .../native/libfreetype/src/psaux/psconv.c | 2 +- .../native/libfreetype/src/psaux/psconv.h | 2 +- .../native/libfreetype/src/psaux/psintrp.c | 2 +- .../native/libfreetype/src/psaux/psobjs.c | 9 +- .../native/libfreetype/src/psaux/psobjs.h | 2 +- .../native/libfreetype/src/psaux/t1cmap.c | 2 +- .../native/libfreetype/src/psaux/t1cmap.h | 2 +- .../native/libfreetype/src/psaux/t1decode.c | 4 +- .../native/libfreetype/src/psaux/t1decode.h | 2 +- .../native/libfreetype/src/pshinter/pshalgo.c | 4 +- .../native/libfreetype/src/pshinter/pshalgo.h | 2 +- .../native/libfreetype/src/pshinter/pshglob.c | 2 +- .../native/libfreetype/src/pshinter/pshglob.h | 2 +- .../native/libfreetype/src/pshinter/pshmod.c | 2 +- .../native/libfreetype/src/pshinter/pshmod.h | 2 +- .../libfreetype/src/pshinter/pshnterr.h | 2 +- .../native/libfreetype/src/pshinter/pshrec.c | 12 +- .../native/libfreetype/src/pshinter/pshrec.h | 2 +- .../native/libfreetype/src/psnames/psmodule.c | 2 +- .../native/libfreetype/src/psnames/psmodule.h | 2 +- .../native/libfreetype/src/psnames/psnamerr.h | 2 +- .../native/libfreetype/src/psnames/pstables.h | 2 +- .../native/libfreetype/src/raster/ftmisc.h | 2 +- .../native/libfreetype/src/raster/ftraster.c | 18 +- .../native/libfreetype/src/raster/ftraster.h | 2 +- .../native/libfreetype/src/raster/ftrend1.c | 2 +- .../native/libfreetype/src/raster/ftrend1.h | 2 +- .../native/libfreetype/src/raster/rasterrs.h | 2 +- .../native/libfreetype/src/sfnt/pngshim.c | 2 +- .../native/libfreetype/src/sfnt/pngshim.h | 2 +- .../native/libfreetype/src/sfnt/sfdriver.c | 4 +- .../native/libfreetype/src/sfnt/sfdriver.h | 2 +- .../native/libfreetype/src/sfnt/sferrors.h | 2 +- .../native/libfreetype/src/sfnt/sfobjs.c | 9 +- .../native/libfreetype/src/sfnt/sfobjs.h | 2 +- .../native/libfreetype/src/sfnt/sfwoff.c | 2 +- .../native/libfreetype/src/sfnt/sfwoff.h | 2 +- .../native/libfreetype/src/sfnt/sfwoff2.c | 8 +- .../native/libfreetype/src/sfnt/sfwoff2.h | 2 +- .../native/libfreetype/src/sfnt/ttcmap.c | 22 +- .../native/libfreetype/src/sfnt/ttcmap.h | 2 +- .../native/libfreetype/src/sfnt/ttcmapc.h | 2 +- .../native/libfreetype/src/sfnt/ttcolr.c | 4 +- .../native/libfreetype/src/sfnt/ttcolr.h | 2 +- .../native/libfreetype/src/sfnt/ttcpal.c | 2 +- .../native/libfreetype/src/sfnt/ttcpal.h | 2 +- .../native/libfreetype/src/sfnt/ttkern.c | 5 +- .../native/libfreetype/src/sfnt/ttkern.h | 8 +- .../native/libfreetype/src/sfnt/ttload.c | 32 +- .../native/libfreetype/src/sfnt/ttload.h | 2 +- .../share/native/libfreetype/src/sfnt/ttmtx.c | 4 +- .../share/native/libfreetype/src/sfnt/ttmtx.h | 2 +- .../native/libfreetype/src/sfnt/ttpost.c | 2 +- .../native/libfreetype/src/sfnt/ttpost.h | 2 +- .../native/libfreetype/src/sfnt/ttsbit.c | 55 +- .../native/libfreetype/src/sfnt/ttsbit.h | 2 +- .../native/libfreetype/src/sfnt/woff2tags.c | 2 +- .../native/libfreetype/src/sfnt/woff2tags.h | 2 +- .../native/libfreetype/src/smooth/ftgrays.c | 84 +- .../native/libfreetype/src/smooth/ftgrays.h | 13 +- .../native/libfreetype/src/smooth/ftsmerrs.h | 2 +- .../native/libfreetype/src/smooth/ftsmooth.c | 2 +- .../native/libfreetype/src/smooth/ftsmooth.h | 2 +- .../libfreetype/src/truetype/ttdriver.c | 6 +- .../libfreetype/src/truetype/ttdriver.h | 2 +- .../libfreetype/src/truetype/tterrors.h | 2 +- .../native/libfreetype/src/truetype/ttgload.c | 423 ++--- .../native/libfreetype/src/truetype/ttgload.h | 2 +- .../native/libfreetype/src/truetype/ttgxvar.c | 702 +++++-- .../native/libfreetype/src/truetype/ttgxvar.h | 7 +- .../libfreetype/src/truetype/ttinterp.c | 1587 +++++++--------- .../libfreetype/src/truetype/ttinterp.h | 128 +- .../native/libfreetype/src/truetype/ttobjs.c | 450 ++--- .../native/libfreetype/src/truetype/ttobjs.h | 127 +- .../native/libfreetype/src/truetype/ttpload.c | 18 +- .../native/libfreetype/src/truetype/ttpload.h | 2 +- .../libfreetype/src/truetype/ttsubpix.c | 1013 ----------- .../libfreetype/src/truetype/ttsubpix.h | 110 -- .../native/libfreetype/src/type1/t1afm.c | 2 +- .../native/libfreetype/src/type1/t1afm.h | 2 +- .../native/libfreetype/src/type1/t1driver.c | 2 +- .../native/libfreetype/src/type1/t1driver.h | 2 +- .../native/libfreetype/src/type1/t1errors.h | 2 +- .../native/libfreetype/src/type1/t1gload.c | 44 +- .../native/libfreetype/src/type1/t1gload.h | 2 +- .../native/libfreetype/src/type1/t1load.c | 8 +- .../native/libfreetype/src/type1/t1load.h | 2 +- .../native/libfreetype/src/type1/t1objs.c | 2 +- .../native/libfreetype/src/type1/t1objs.h | 2 +- .../native/libfreetype/src/type1/t1parse.c | 2 +- .../native/libfreetype/src/type1/t1parse.h | 2 +- .../native/libfreetype/src/type1/t1tokens.h | 2 +- .../html/CSS/8231286/HtmlFontSizeTest.java | 18 +- 286 files changed, 7169 insertions(+), 4787 deletions(-) create mode 100644 src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c create mode 100644 src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h create mode 100644 src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c create mode 100644 src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h delete mode 100644 src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c delete mode 100644 src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h diff --git a/src/java.desktop/share/legal/freetype.md b/src/java.desktop/share/legal/freetype.md index 5df525e2f67..cf2518df594 100644 --- a/src/java.desktop/share/legal/freetype.md +++ b/src/java.desktop/share/legal/freetype.md @@ -1,4 +1,4 @@ -## The FreeType Project: Freetype v2.13.3 +## The FreeType Project: Freetype v2.14.1 ### FreeType Notice @@ -21,25 +21,24 @@ which fits your needs best. ### FreeType License ``` -Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2007-2024 by Dereg Clegg and Michael Toftdal. -Copyright (C) 1996-2024 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and -Copyright (C) 2004-2024 by Masatake YAMATO and Redhat K.K. -Copyright (C) 2007-2024 by Derek Clegg and Michael Toftdal. -Copyright (C) 2003-2024 by Masatake YAMATO, Red Hat K.K., -Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. -Copyright (C) 2007-2024 by David Turner. -Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. -Copyright (C) 2007-2024 by Rahul Bhalerao , . -Copyright (C) 2008-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. -Copyright (C) 2013-2024 by Google, Inc. -Copyright (C) 2019-2024 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2009-2024 by Oran Agra and Mickey Gabel. -Copyright (C) 2018-2024 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. -Copyright (C) 2004-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. - - +Copyright (C) 1996-2025 by David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2007-2025 by Dereg Clegg and Michael Toftdal. +Copyright (C) 1996-2025 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2022-2025 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and +Copyright (C) 2004-2025 by Masatake YAMATO and Redhat K.K. +Copyright (C) 2007-2025 by Derek Clegg and Michael Toftdal. +Copyright (C) 2003-2025 by Masatake YAMATO, Red Hat K.K., +Copyright (C) 1996-2025 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. +Copyright (C) 2007-2025 by David Turner. +Copyright (C) 2022-2025 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. +Copyright (C) 2007-2025 by Rahul Bhalerao , . +Copyright (C) 2025 by Behdad Esfahbod. +Copyright (C) 2008-2025 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. +Copyright (C) 2013-2025 by Google, Inc. +Copyright (C) 2019-2025 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2009-2025 by Oran Agra and Mickey Gabel. +Copyright (C) 2018-2025 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. +Copyright (C) 2004-2025 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. The FreeType Project LICENSE ---------------------------- @@ -207,6 +206,7 @@ Legal Terms https://www.freetype.org + ``` ### GPL v2 diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h index 0667493fec6..d66c5df9976 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h @@ -4,7 +4,7 @@ * * ANSI-specific configuration file (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h index f6ef2618ded..16eab9048fc 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h @@ -4,7 +4,7 @@ * * Build macros of the FreeType 2 library. * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h index d29a0a7cefb..be7a4c50dc3 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h @@ -4,7 +4,7 @@ * * User-selectable configuration macros (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -158,12 +158,12 @@ FT_BEGIN_HEADER /************************************************************************** * - * If this macro is defined, try to use an inlined assembler version of the - * @FT_MulFix function, which is a 'hotspot' when loading and hinting - * glyphs, and which should be executed as fast as possible. + * If this macro is defined, try to use an inlined 64-bit or assembler + * version of the @FT_MulFix function, which is a 'hotspot' when loading + * and hinting glyphs, and which should be executed as fast as possible. * - * Note that if your compiler or CPU is not supported, this will default to - * the standard and portable implementation found in `ftcalc.c`. + * If your compiler is not C99-compliant or CPU assembly is not supported, + * you can disable this option. */ #define FT_CONFIG_OPTION_INLINE_MULFIX @@ -293,6 +293,31 @@ FT_BEGIN_HEADER /* #define FT_CONFIG_OPTION_USE_HARFBUZZ */ + /************************************************************************** + * + * HarfBuzz dynamic support. + * + * Define this macro if you want the HarfBuzz library to be loaded at + * runtime instead of being linked to FreeType. + * + * This option has no effect if `FT_CONFIG_OPTION_USE_HARFBUZZ` is not + * defined. + * + * When this option is enabled, FreeType will try to load the HarfBuzz + * library at runtime, using `dlopen` or `LoadLibrary`, depending on the + * platform. On Microsoft platforms, the library name looked up is + * `libharfbuzz-0.dll`. On Apple platforms, the library name looked up + * is `libharfbuzz.0.dylib`. On all other platforms, the library name + * looked up is `libharfbuzz.so.0`. This name can be overridden by + * defining the macro `FT_LIBHARFBUZZ` at FreeType compilation time. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ + + /************************************************************************** * * Brotli support. @@ -679,7 +704,7 @@ FT_BEGIN_HEADER * defined. * * [1] - * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx + * https://learn.microsoft.com/typography/cleartype/truetypecleartype */ #define TT_CONFIG_OPTION_SUBPIXEL_HINTING @@ -697,7 +722,7 @@ FT_BEGIN_HEADER * flags array which can be used to disambiguate, but old fonts will not * have them. * - * https://www.microsoft.com/typography/otspec/glyf.htm + * https://learn.microsoft.com/typography/opentype/spec/glyf * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html */ #undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED @@ -760,10 +785,10 @@ FT_BEGIN_HEADER /************************************************************************** * * Option `TT_CONFIG_OPTION_GPOS_KERNING` enables a basic GPOS kerning - * implementation (for TrueType fonts only). With this defined, FreeType - * is able to get kerning pair data from the GPOS 'kern' feature as well as - * legacy 'kern' tables; without this defined, FreeType will only be able - * to use legacy 'kern' tables. + * implementation (for TrueType and OpenType fonts only). With this + * defined, FreeType is able to get kerning pair data from the GPOS 'kern' + * feature as well as legacy 'kern' tables; without this defined, FreeType + * will only be able to use legacy 'kern' tables. * * Note that FreeType does not support more advanced GPOS layout features; * even the 'kern' feature implemented here doesn't handle more diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h index e17aa7b89d5..f846b4456c1 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h @@ -5,7 +5,7 @@ * ANSI-specific library and header configuration file (specification * only). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h index c27505ffc4b..a0b892ece4b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h @@ -4,7 +4,7 @@ * * FreeType integer types definitions. * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -17,6 +17,8 @@ #ifndef FREETYPE_CONFIG_INTEGER_TYPES_H_ #define FREETYPE_CONFIG_INTEGER_TYPES_H_ +FT_BEGIN_HEADER + /* There are systems (like the Texas Instruments 'C54x) where a `char` */ /* has 16~bits. ANSI~C says that `sizeof(char)` is always~1. Since an */ /* `int` has 16~bits also for this system, `sizeof(int)` gives~1 which */ @@ -242,9 +244,34 @@ #endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ #ifdef FT_INT64 + typedef FT_INT64 FT_Int64; typedef FT_UINT64 FT_UInt64; -#endif +# define FT_INT64_ZERO 0 + +#else /* !FT_INT64 */ + + /* we need to emulate 64-bit data types if none are available */ + + typedef struct FT_Int64_ + { + FT_UInt32 lo; + FT_UInt32 hi; + + } FT_Int64; + + typedef struct FT_UInt64_ + { + FT_UInt32 lo; + FT_UInt32 hi; + + } FT_UInt64; + +# define FT_INT64_ZERO { 0, 0 } + +#endif /* !FT_INT64 */ + +FT_END_HEADER #endif /* FREETYPE_CONFIG_INTEGER_TYPES_H_ */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h index 07b6f915bd8..d1b6a9898fd 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h @@ -4,7 +4,7 @@ * * Mac/OS X support configuration header. * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h index f56581a6ee7..9f28b394737 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h @@ -4,7 +4,7 @@ * * Define a set of compiler macros used in public FreeType headers. * - * Copyright (C) 2020-2024 by + * Copyright (C) 2020-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -62,8 +62,8 @@ FT_BEGIN_HEADER * because it is needed by `FT_EXPORT`. */ - /* Visual C, mingw */ -#if defined( _WIN32 ) + /* Visual C, MinGW, Cygwin */ +#if defined( _WIN32 ) || defined( __CYGWIN__ ) #if defined( FT2_BUILD_LIBRARY ) && defined( DLL_EXPORT ) #define FT_PUBLIC_FUNCTION_ATTRIBUTE __declspec( dllexport ) diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h index 58fc33dfe60..1e249235882 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h @@ -4,7 +4,7 @@ * * FreeType high-level API and common types (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -811,7 +811,7 @@ FT_BEGIN_HEADER * FT_ENCODING_MS_SYMBOL :: * Microsoft Symbol encoding, used to encode mathematical symbols and * wingdings. For more information, see - * 'https://www.microsoft.com/typography/otspec/recom.htm#non-standard-symbol-fonts', + * 'https://learn.microsoft.com/typography/opentype/spec/recom#non-standard-symbol-fonts', * 'http://www.kostis.net/charsets/symbol.htm', and * 'http://www.kostis.net/charsets/wingding.htm'. * @@ -1068,12 +1068,12 @@ FT_BEGIN_HEADER * the face in the font file (starting with value~0). They are set * to~0 if there is only one face in the font file. * - * [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation - * fonts only, holding the named instance index for the current face - * index (starting with value~1; value~0 indicates font access without - * a named instance). For non-variation fonts, bits 16-30 are ignored. - * If we have the third named instance of face~4, say, `face_index` is - * set to 0x00030004. + * [Since 2.6.1] Bits 16-30 are relevant to TrueType GX and OpenType + * Font Variations only, holding the named instance index for the + * current face index (starting with value~1; value~0 indicates font + * access without a named instance). For non-variation fonts, bits + * 16-30 are ignored. If we have the third named instance of face~4, + * say, `face_index` is set to 0x00030004. * * Bit 31 is always zero (that is, `face_index` is always a positive * value). @@ -1092,10 +1092,10 @@ FT_BEGIN_HEADER * the face; see @FT_STYLE_FLAG_XXX for the details. * * [Since 2.6.1] Bits 16-30 hold the number of named instances - * available for the current face if we have a GX or OpenType variation - * (sub)font. Bit 31 is always zero (that is, `style_flags` is always - * a positive value). Note that a variation font has always at least - * one named instance, namely the default instance. + * available for the current face if we have a TrueType GX or OpenType + * Font Variation. Bit 31 is always zero (that is, `style_flags` is + * always a positive value). Note that a variation font has always at + * least one named instance, namely the default instance. * * num_glyphs :: * The number of glyphs in the face. If the face is scalable and has @@ -1159,7 +1159,7 @@ FT_BEGIN_HEADER * Note that the bounding box might be off by (at least) one pixel for * hinted fonts. See @FT_Size_Metrics for further discussion. * - * Note that the bounding box does not vary in OpenType variation fonts + * Note that the bounding box does not vary in OpenType Font Variations * and should only be used in relation to the default instance. * * units_per_EM :: @@ -1218,7 +1218,7 @@ FT_BEGIN_HEADER * Fields may be changed after a call to @FT_Attach_File or * @FT_Attach_Stream. * - * For an OpenType variation font, the values of the following fields can + * For OpenType Font Variations, the values of the following fields can * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if * the font contains an 'MVAR' table: `ascender`, `descender`, `height`, * `underline_position`, and `underline_thickness`. @@ -1336,7 +1336,7 @@ FT_BEGIN_HEADER * FT_FACE_FLAG_MULTIPLE_MASTERS :: * The face contains multiple masters and is capable of interpolating * between them. Supported formats are Adobe MM, TrueType GX, and - * OpenType variation fonts. + * OpenType Font Variations. * * See section @multiple_masters for API details. * @@ -1609,7 +1609,7 @@ FT_BEGIN_HEADER * * @description: * A macro that returns true whenever a face object is a named instance - * of a GX or OpenType variation font. + * of a TrueType GX or OpenType Font Variations. * * [Since 2.9] Changing the design coordinates with * @FT_Set_Var_Design_Coordinates or @FT_Set_Var_Blend_Coordinates does @@ -2147,7 +2147,7 @@ FT_BEGIN_HEADER * freed. * * [Since 2.10.1] If @FT_LOAD_NO_SCALE is set, outline coordinates of - * OpenType variation fonts for a selected instance are internally + * OpenType Font Variations for a selected instance are internally * handled as 26.6 fractional font units but returned as (rounded) * integers, as expected. To get unrounded font units, don't use * @FT_LOAD_NO_SCALE but load the glyph with @FT_LOAD_NO_HINTING and @@ -2640,14 +2640,14 @@ FT_BEGIN_HEADER * the face in the font file (starting with value~0). Set it to~0 if * there is only one face in the font file. * - * [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation - * fonts only, specifying the named instance index for the current face - * index (starting with value~1; value~0 makes FreeType ignore named - * instances). For non-variation fonts, bits 16-30 are ignored. - * Assuming that you want to access the third named instance in face~4, - * `face_index` should be set to 0x00030004. If you want to access - * face~4 without variation handling, simply set `face_index` to - * value~4. + * [Since 2.6.1] Bits 16-30 are relevant to TrueType GX and OpenType + * Font Variations only, specifying the named instance index for the + * current face index (starting with value~1; value~0 makes FreeType + * ignore named instances). For non-variation fonts, bits 16-30 are + * ignored. Assuming that you want to access the third named instance + * in face~4, `face_index` should be set to 0x00030004. If you want + * to access face~4 without variation handling, simply set + * `face_index` to value~4. * * `FT_Open_Face` and its siblings can be used to quickly check whether * the font format of a given font resource is supported by FreeType. @@ -2914,11 +2914,11 @@ FT_BEGIN_HEADER * of the available glyphs at a given ppem value is available. FreeType * silently uses outlines if there is no bitmap for a given glyph index. * - * For GX and OpenType variation fonts, a bitmap strike makes sense only - * if the default instance is active (that is, no glyph variation takes - * place); otherwise, FreeType simply ignores bitmap strikes. The same - * is true for all named instances that are different from the default - * instance. + * For TrueType GX and OpenType Font Variations, a bitmap strike makes + * sense only if the default instance is active (that is, no glyph + * variation takes place); otherwise, FreeType simply ignores bitmap + * strikes. The same is true for all named instances that are different + * from the default instance. * * Don't use this function if you are using the FreeType cache API. */ @@ -3078,7 +3078,7 @@ FT_BEGIN_HEADER * is dependent entirely on how the size is defined in the source face. * The font designer chooses the final size of each glyph relative to * this size. For more information refer to - * 'https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'. + * 'https://freetype.org/freetype2/docs/glyphs/glyphs-2.html'. * * Contrary to @FT_Set_Char_Size, this function doesn't have special code * to normalize zero-valued widths, heights, or resolutions, which are @@ -3441,8 +3441,10 @@ FT_BEGIN_HEADER * blending of the color glyph layers associated with the glyph index, * using the same bitmap format as embedded color bitmap images. This * is mainly for convenience and works only for glyphs in 'COLR' v0 - * tables (or glyphs in 'COLR' v1 tables that exclusively use v0 - * features). For full control of color layers use + * tables. **There is no rendering support for 'COLR' v1** (with the + * exception of v1 tables that exclusively use v0 features)! You need + * a graphics library like Skia or Cairo to interpret the graphics + * commands stored in v1 tables. For full control of color layers use * @FT_Get_Color_Glyph_Layer and FreeType's color functions like * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering * so that the client application can handle blending by itself. @@ -3895,8 +3897,10 @@ FT_BEGIN_HEADER * * This process can cost performance. There is an approximation that * does not need to know about the background color; see - * https://bel.fi/alankila/lcd/ and - * https://bel.fi/alankila/lcd/alpcor.html for details. + * https://web.archive.org/web/20211019204945/https://bel.fi/alankila/lcd/ + * and + * https://web.archive.org/web/20210211002939/https://bel.fi/alankila/lcd/alpcor.html + * for details. * * **ATTENTION**: Linear blending is even more important when dealing * with subpixel-rendered glyphs to prevent color-fringing! A @@ -3993,13 +3997,13 @@ FT_BEGIN_HEADER * out of the scope of this API function -- they can be implemented * through format-specific interfaces. * - * Note that, for TrueType fonts only, this can extract data from both - * the 'kern' table and the basic, pair-wise kerning feature from the - * GPOS table (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though - * FreeType does not support the more advanced GPOS layout features; use - * a library like HarfBuzz for those instead. If a font has both a - * 'kern' table and kern features of a GPOS table, the 'kern' table will - * be used. + * Note that, for TrueType and OpenType fonts only, this can extract data + * from both the 'kern' table and the basic, pair-wise kerning feature + * from the GPOS table (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), + * though FreeType does not support the more advanced GPOS layout + * features; use a library like HarfBuzz for those instead. If a font + * has both a 'kern' table and kern features of a GPOS table, the 'kern' + * table will be used. * * Also note for right-to-left scripts, the functionality may differ for * fonts with GPOS tables vs. 'kern' tables. For GPOS, right-to-left @@ -4530,7 +4534,7 @@ FT_BEGIN_HEADER * table description in the OpenType specification for the meaning of the * various flags (which get synthesized for non-OpenType subglyphs). * - * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description + * https://learn.microsoft.com/typography/opentype/spec/glyf#composite-glyph-description * * @values: * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS :: @@ -4593,7 +4597,7 @@ FT_BEGIN_HEADER * interpreted depending on the flags returned in `*p_flags`. See the * OpenType specification for details. * - * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description + * https://learn.microsoft.com/typography/opentype/spec/glyf#composite-glyph-description * */ FT_EXPORT( FT_Error ) @@ -4619,7 +4623,7 @@ FT_BEGIN_HEADER * associated with a font. * * See - * https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf + * https://adobe-type-tools.github.io/font-tech-notes/pdfs/AcrobatDC_FontPolicies.pdf * for more details. * * @values: @@ -5173,8 +5177,8 @@ FT_BEGIN_HEADER * */ #define FREETYPE_MAJOR 2 -#define FREETYPE_MINOR 13 -#define FREETYPE_PATCH 3 +#define FREETYPE_MINOR 14 +#define FREETYPE_PATCH 1 /************************************************************************** diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h index 85b8ba2554b..62a856ccbd7 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h @@ -4,7 +4,7 @@ * * Quick computation of advance widths (specification only). * - * Copyright (C) 2008-2024 by + * Copyright (C) 2008-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h index 12bbfa63a62..348b4b3a268 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h @@ -4,7 +4,7 @@ * * FreeType exact bbox computation (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h index 6f63b0b1e78..faad25689c9 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h @@ -4,7 +4,7 @@ * * FreeType API for accessing BDF-specific strings (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h index df9d462652e..a22d43adf14 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (specification). * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h index 96b2a90fc59..7cda8ff3f39 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information (specification). * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * Dereg Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h index 420720ddf22..129b1a23fb0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h @@ -4,7 +4,7 @@ * * FreeType's glyph color management (specification). * - * Copyright (C) 2018-2024 by + * Copyright (C) 2018-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -317,6 +317,15 @@ FT_BEGIN_HEADER * @description: * The functions described here allow access of colored glyph layer data * in OpenType's 'COLR' tables. + * + * Note that FreeType does *not* provide rendering in general of glyphs + * that use a 'COLR' table! While FreeType has very limited rendering + * support for 'COLR' v0 tables (without a possibility to change the + * color palette) via @FT_Render_Glyph, there is no such convenience + * code for 'COLR' v1 tables -- while it appears that v1 is simply an + * 'improved' version of v0, this is not the case: it is a completely + * different color font format, and you need a dedicated graphics + * library like Skia or Cairo to handle a v1 table's drawing commands. */ @@ -359,7 +368,7 @@ FT_BEGIN_HEADER * iteratively retrieve the colored glyph layers associated with the * current glyph slot. * - * https://docs.microsoft.com/en-us/typography/opentype/spec/colr + * https://learn.microsoft.com/typography/opentype/spec/colr * * The glyph layer data for a given glyph index, if present, provides an * alternative, multi-color glyph representation: Instead of rendering @@ -1518,7 +1527,7 @@ FT_BEGIN_HEADER * * @return: * Value~1 if a clip box is found. If no clip box is found or an error - * occured, value~0 is returned. + * occurred, value~0 is returned. * * @note: * To retrieve the clip box in font units, reset scale to units-per-em @@ -1646,7 +1655,7 @@ FT_BEGIN_HEADER * * @return: * Value~1 if everything is OK. Value~0 if no details can be found for - * this paint or any other error occured. + * this paint or any other error occurred. * * @since: * 2.13 diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h index 1b7f539f5e2..b65a06ab69b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h @@ -4,7 +4,7 @@ * * FreeType API for controlling driver modules (specification only). * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -282,7 +282,7 @@ FT_BEGIN_HEADER * minimize hinting techniques that were problematic with the extra * resolution of ClearType; see * http://rastertragedy.com/RTRCh4.htm#Sec1 and - * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx. + * https://learn.microsoft.com/typography/cleartype/truetypecleartype. * This technique is not to be confused with ClearType compatible widths. * ClearType backward compatibility has no direct impact on changing * advance widths, but there might be an indirect impact on disabling @@ -784,7 +784,7 @@ FT_BEGIN_HEADER * * Details on subpixel hinting and some of the necessary tweaks can be * found in Greg Hitchcock's whitepaper at - * 'https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'. + * 'https://learn.microsoft.com/typography/cleartype/truetypecleartype'. * Note that FreeType currently doesn't really 'subpixel hint' (6x1, 6x2, * or 6x5 supersampling) like discussed in the paper. Depending on the * chosen interpreter, it simply ignores instructions on vertical stems diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h index 710ca91bbdd..3e591bede8d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h @@ -4,7 +4,7 @@ * * FreeType error codes (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h index 27c0ece5c1c..eca494f90c0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h @@ -4,7 +4,7 @@ * * FreeType error code handling (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h index 7c8b0874a81..5df82447d0e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h @@ -4,7 +4,7 @@ * * Support functions for font formats. * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h index 30e5a9bf82b..77e5a7e7bfd 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h @@ -4,7 +4,7 @@ * * Access of TrueType's 'gasp' table (specification). * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h index dc1eb8873ae..3691781cf52 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h index 9516dc030ac..e26c334c11a 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h @@ -4,7 +4,7 @@ * * Gzip-compressed stream support. * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h index 2b4b4ac60ae..b0a0172ef4f 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h @@ -5,7 +5,7 @@ * FreeType glyph image formats and default raster interface * (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -267,6 +267,10 @@ FT_BEGIN_HEADER * *logical* one. For example, if @FT_Pixel_Mode is set to * `FT_PIXEL_MODE_LCD`, the logical width is a just a third of the * physical one. + * + * An empty bitmap with a NULL `buffer` is valid, with `rows` and/or + * `pitch` also set to 0. Such bitmaps might be produced while rendering + * empty or degenerate outlines. */ typedef struct FT_Bitmap_ { @@ -439,7 +443,7 @@ FT_BEGIN_HEADER * rasterizer; see the `tags` field in @FT_Outline. * * Please refer to the description of the 'SCANTYPE' instruction in the - * [OpenType specification](https://learn.microsoft.com/en-us/typography/opentype/spec/tt_instructions#scantype) + * [OpenType specification](https://learn.microsoft.com/typography/opentype/spec/tt_instructions#scantype) * how simple drop-outs, smart drop-outs, and stubs are defined. */ #define FT_OUTLINE_NONE 0x0 diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h index 816581b78eb..2233044754e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h @@ -4,7 +4,7 @@ * * FreeType incremental loading (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h index 25274dc4ac2..a0a8e9da929 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h @@ -5,7 +5,7 @@ * FreeType API for color filtering of subpixel bitmap glyphs * (specification). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h index 972fbfa2fe4..14958b0ff37 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h @@ -4,7 +4,7 @@ * * Generic list support for FreeType (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h index 1813cfc2c27..d155171136c 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h @@ -4,7 +4,7 @@ * * Additional debugging APIs. * - * Copyright (C) 2020-2024 by + * Copyright (C) 2020-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h index e4efde33dd8..c5ac49101a4 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h @@ -4,7 +4,7 @@ * * Additional Mac-specific API. * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h index 35ed039c89b..ff0bbab59f9 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h @@ -2,9 +2,9 @@ * * ftmm.h * - * FreeType Multiple Master font interface (specification). + * FreeType variation font interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -37,24 +37,79 @@ FT_BEGIN_HEADER * multiple_masters * * @title: - * Multiple Masters + * OpenType Font Variations, TrueType GX, and Adobe MM Fonts * * @abstract: - * How to manage Multiple Masters fonts. + * How to manage variable fonts with multiple design axes. * * @description: - * The following types and functions are used to manage Multiple Master - * fonts, i.e., the selection of specific design instances by setting - * design axis coordinates. + * The following types and functions manage OpenType Font Variations, + * Adobe Multiple Master (MM) fonts, and Apple TrueType GX fonts. These + * formats have in common that they allow the selection of specific + * design instances by setting design coordinates for one or more axes + * like font weight or width. * - * Besides Adobe MM fonts, the interface supports Apple's TrueType GX and - * OpenType variation fonts. Some of the routines only work with Adobe - * MM fonts, others will work with all three types. They are similar - * enough that a consistent interface makes sense. + * For historical reasons there are two interfaces. The first, older one + * can be used with Adobe MM fonts only, and the second, newer one is a + * unified interface that handles all three font formats. However, some + * differences remain and are documented accordingly; in particular, + * Adobe MM fonts don't have named instances (see below). * - * For Adobe MM fonts, macro @FT_IS_SFNT returns false. For GX and - * OpenType variation fonts, it returns true. + * For Adobe MM fonts, macro @FT_IS_SFNT returns false. For TrueType GX + * and OpenType Font Variations, it returns true. * + * We use mostly the terminology of the OpenType standard. Here are some + * important technical terms. + * + * * A 'named instance' is a tuple of design coordinates that has a + * string ID (i.e., an index into the font's 'name' table) associated + * with it. The font can tell the user that, for example, + * [Weight=700,Width=110] is 'Bold'. Another name for 'named instance' + * is 'named style'. + * + * Adobe MM fonts don't have named instances. + * + * * The 'default instance' of a variation font is that instance for + * which the nth axis coordinate is equal to the nth default axis + * coordinate (i.e., `axis[n].def` as specified in the @FT_MM_Var + * structure), with~n covering all axes. In TrueType GX and OpenType + * Font Variations, the default instance is explicitly given. In Adobe + * MM fonts, the `WeightVector` entry as found in the font file is + * taken as the default instance. + * + * For TrueType GX and OpenType Font Variations, FreeType synthesizes + * a named instance for the default instance if the font does not + * contain such an entry. + * + * * 'Design coordinates' are the axis values found in a variation font + * file. Their meaning is specified by the font designer and the + * values are rather arbitrary. + * + * For example, the 'weight' axis in design coordinates might vary + * between 100 (thin) and 900 (heavy) in font~A, while font~B + * contains values between 400 (normal) and 800 (extra bold). + * + * * 'Normalized coordinates' are design coordinates mapped to a standard + * range; they are also called 'blend coordinates'. + * + * For TrueType GX and OpenType Font Variations, the range is [-1;1], + * with the minimum mapped to value~-1, the default mapped to + * value~0, and the maximum mapped to value~1, and all other + * coordinates mapped to intervening points. Please look up the + * [OpenType + * specification](https://learn.microsoft.com/en-us/typography/opentype/spec/otvaroverview) + * on how this mapping works in detail. + * + * For Adobe MM fonts, this standard range is [0;1], with the minimum + * mapped to value~0 and the maximum mapped to value~1, and all other + * coordinates mapped to intervening points. Please look up [Adobe + * TechNote + * #5015](https://adobe-type-tools.github.io/font-tech-notes/pdfs/5015.Type1_Supp.pdf) + * on how this mapping works in detail. + * + * Assuming that the two fonts in the previous example are OpenType + * Font Variations, both font~A's [100;900] and font~B's [400;800] + * coordinate ranges get mapped to [-1;1]. */ @@ -64,14 +119,14 @@ FT_BEGIN_HEADER * T1_MAX_MM_XXX * * @description: - * Multiple Masters limits as defined in their specifications. + * Adobe MM font limits as defined in their specifications. * * @values: * T1_MAX_MM_AXIS :: - * The maximum number of Multiple Masters axes. + * The maximum number of Adobe MM font axes. * * T1_MAX_MM_DESIGNS :: - * The maximum number of Multiple Masters designs. + * The maximum number of Adobe MM font designs. * * T1_MAX_MM_MAP_POINTS :: * The maximum number of elements in a design map. @@ -88,11 +143,10 @@ FT_BEGIN_HEADER * FT_MM_Axis * * @description: - * A structure to model a given axis in design space for Multiple Masters - * fonts. + * A structure to model a given axis in design space for Adobe MM fonts. * - * This structure can't be used for TrueType GX or OpenType variation - * fonts. + * This structure can't be used with TrueType GX or OpenType Font + * Variations. * * @fields: * name :: @@ -119,17 +173,17 @@ FT_BEGIN_HEADER * FT_Multi_Master * * @description: - * A structure to model the axes and space of a Multiple Masters font. + * A structure to model the axes and space of an Adobe MM font. * - * This structure can't be used for TrueType GX or OpenType variation - * fonts. + * This structure can't be used with TrueType GX or OpenType Font + * Variations. * * @fields: * num_axis :: * Number of axes. Cannot exceed~4. * * num_designs :: - * Number of designs; should be normally 2^num_axis even though the + * Number of designs; should be normally `2^num_axis` even though the * Type~1 specification strangely allows for intermediate designs to be * present. This number cannot exceed~16. * @@ -151,13 +205,13 @@ FT_BEGIN_HEADER * FT_Var_Axis * * @description: - * A structure to model a given axis in design space for Multiple - * Masters, TrueType GX, and OpenType variation fonts. + * A structure to model a given axis in design space for Adobe MM fonts, + * TrueType GX, and OpenType Font Variations. * * @fields: * name :: * The axis's name. Not always meaningful for TrueType GX or OpenType - * variation fonts. + * Font Variations. * * minimum :: * The axis's minimum design coordinate. @@ -171,17 +225,17 @@ FT_BEGIN_HEADER * * tag :: * The axis's tag (the equivalent to 'name' for TrueType GX and - * OpenType variation fonts). FreeType provides default values for + * OpenType Font Variations). FreeType provides default values for * Adobe MM fonts if possible. * * strid :: * The axis name entry in the font's 'name' table. This is another * (and often better) version of the 'name' field for TrueType GX or - * OpenType variation fonts. Not meaningful for Adobe MM fonts. + * OpenType Font Variations. Not meaningful for Adobe MM fonts. * * @note: * The fields `minimum`, `def`, and `maximum` are 16.16 fractional values - * for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the + * for TrueType GX and OpenType Font Variations. For Adobe MM fonts, the * values are whole numbers (i.e., the fractional part is zero). */ typedef struct FT_Var_Axis_ @@ -205,7 +259,7 @@ FT_BEGIN_HEADER * * @description: * A structure to model a named instance in a TrueType GX or OpenType - * variation font. + * Font Variations. * * This structure can't be used for Adobe MM fonts. * @@ -215,11 +269,11 @@ FT_BEGIN_HEADER * entry for each axis. * * strid :: - * The entry in 'name' table identifying this instance. + * An index into the 'name' table identifying this instance. * * psid :: - * The entry in 'name' table identifying a PostScript name for this - * instance. Value 0xFFFF indicates a missing entry. + * An index into the 'name' table identifying a PostScript name for + * this instance. Value 0xFFFF indicates a missing entry. */ typedef struct FT_Var_Named_Style_ { @@ -236,39 +290,33 @@ FT_BEGIN_HEADER * FT_MM_Var * * @description: - * A structure to model the axes and space of an Adobe MM, TrueType GX, - * or OpenType variation font. + * A structure to model the axes and space of Adobe MM fonts, TrueType + * GX, or OpenType Font Variations. * * Some fields are specific to one format and not to the others. * * @fields: * num_axis :: * The number of axes. The maximum value is~4 for Adobe MM fonts; no - * limit in TrueType GX or OpenType variation fonts. + * limit in TrueType GX or OpenType Font Variations. * * num_designs :: - * The number of designs; should be normally 2^num_axis for Adobe MM - * fonts. Not meaningful for TrueType GX or OpenType variation fonts + * The number of designs; should be normally `2^num_axis` for Adobe MM + * fonts. Not meaningful for TrueType GX or OpenType Font Variations * (where every glyph could have a different number of designs). * * num_namedstyles :: - * The number of named styles; a 'named style' is a tuple of design - * coordinates that has a string ID (in the 'name' table) associated - * with it. The font can tell the user that, for example, - * [Weight=1.5,Width=1.1] is 'Bold'. Another name for 'named style' is - * 'named instance'. - * - * For Adobe Multiple Masters fonts, this value is always zero because - * the format does not support named styles. + * The number of named instances. For Adobe MM fonts, this value is + * always zero. * * axis :: - * An axis descriptor table. TrueType GX and OpenType variation fonts + * An axis descriptor table. TrueType GX and OpenType Font Variations * contain slightly more data than Adobe MM fonts. Memory management * of this pointer is done internally by FreeType. * * namedstyle :: - * A named style (instance) table. Only meaningful for TrueType GX and - * OpenType variation fonts. Memory management of this pointer is done + * An array of named instances. Only meaningful for TrueType GX and + * OpenType Font Variations. Memory management of this pointer is done * internally by FreeType. */ typedef struct FT_MM_Var_ @@ -290,8 +338,8 @@ FT_BEGIN_HEADER * @description: * Retrieve a variation descriptor of a given Adobe MM font. * - * This function can't be used with TrueType GX or OpenType variation - * fonts. + * This function can't be used with TrueType GX or OpenType Font + * Variations. * * @input: * face :: @@ -299,7 +347,7 @@ FT_BEGIN_HEADER * * @output: * amaster :: - * The Multiple Masters descriptor. + * The Adobe MM font's variation descriptor. * * @return: * FreeType error code. 0~means success. @@ -366,8 +414,8 @@ FT_BEGIN_HEADER * For Adobe MM fonts, choose an interpolated font design through design * coordinates. * - * This function can't be used with TrueType GX or OpenType variation - * fonts. + * This function can't be used with TrueType GX or OpenType Font + * Variations. * * @inout: * face :: @@ -391,8 +439,8 @@ FT_BEGIN_HEADER * * [Since 2.9] If `num_coords` is larger than zero, this function sets * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field - * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero, - * this bit flag gets unset. + * (i.e., @FT_IS_VARIATION returns true). If `num_coords` is zero, this + * bit flag gets unset. */ FT_EXPORT( FT_Error ) FT_Set_MM_Design_Coordinates( FT_Face face, @@ -428,7 +476,7 @@ FT_BEGIN_HEADER * * @note: * The design coordinates are 16.16 fractional values for TrueType GX and - * OpenType variation fonts. For Adobe MM fonts, the values are supposed + * OpenType Font Variations. For Adobe MM fonts, the values are supposed * to be whole numbers (i.e., the fractional part is zero). * * [Since 2.8.1] To reset all axes to the default values, call the @@ -438,8 +486,14 @@ FT_BEGIN_HEADER * * [Since 2.9] If `num_coords` is larger than zero, this function sets * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field - * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero, - * this bit flag gets unset. + * (i.e., @FT_IS_VARIATION returns true). If `num_coords` is zero, this + * bit flag gets unset. + * + * [Since 2.14] This function also sets the @FT_FACE_FLAG_VARIATION bit + * in @FT_Face's `face_flags` field (i.e., @FT_IS_VARIATION returns + * true) if any of the provided coordinates is different from the face's + * default value for the corresponding axis, that is, the set up face is + * not at its default position. */ FT_EXPORT( FT_Error ) FT_Set_Var_Design_Coordinates( FT_Face face, @@ -468,14 +522,14 @@ FT_BEGIN_HEADER * * @output: * coords :: - * The design coordinates array. + * The design coordinates array, which must be allocated by the user. * * @return: * FreeType error code. 0~means success. * * @note: * The design coordinates are 16.16 fractional values for TrueType GX and - * OpenType variation fonts. For Adobe MM fonts, the values are whole + * OpenType Font Variations. For Adobe MM fonts, the values are whole * numbers (i.e., the fractional part is zero). * * @since: @@ -493,8 +547,7 @@ FT_BEGIN_HEADER * FT_Set_MM_Blend_Coordinates * * @description: - * Choose an interpolated font design through normalized blend - * coordinates. + * Choose an interpolated font design through normalized coordinates. * * This function works with all supported variation formats. * @@ -509,9 +562,10 @@ FT_BEGIN_HEADER * the number of axes, use default values for the remaining axes. * * coords :: - * The design coordinates array. Each element is a 16.16 fractional - * value and must be between 0 and 1.0 for Adobe MM fonts, and between - * -1.0 and 1.0 for TrueType GX and OpenType variation fonts. + * The normalized coordinates array. Each element is a 16.16 + * fractional value and must be between 0 and 1.0 for Adobe MM fonts, + * and between -1.0 and 1.0 for TrueType GX and OpenType Font + * Variations. * * @return: * FreeType error code. 0~means success. @@ -524,8 +578,14 @@ FT_BEGIN_HEADER * * [Since 2.9] If `num_coords` is larger than zero, this function sets * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field - * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero, - * this bit flag gets unset. + * (i.e., @FT_IS_VARIATION returns true). If `num_coords` is zero, this + * bit flag gets unset. + * + * [Since 2.14] This function also sets the @FT_FACE_FLAG_VARIATION bit + * in @FT_Face's `face_flags` field (i.e., @FT_IS_VARIATION returns + * true) if any of the provided coordinates is different from the face's + * default value for the corresponding axis, that is, the set up face is + * not at its default position. */ FT_EXPORT( FT_Error ) FT_Set_MM_Blend_Coordinates( FT_Face face, @@ -539,8 +599,8 @@ FT_BEGIN_HEADER * FT_Get_MM_Blend_Coordinates * * @description: - * Get the normalized blend coordinates of the currently selected - * interpolated font. + * Get the normalized coordinates of the currently selected interpolated + * font. * * This function works with all supported variation formats. * @@ -549,14 +609,14 @@ FT_BEGIN_HEADER * A handle to the source face. * * num_coords :: - * The number of normalized blend coordinates to retrieve. If it is - * larger than the number of axes, set the excess values to~0.5 for - * Adobe MM fonts, and to~0 for TrueType GX and OpenType variation - * fonts. + * The number of normalized coordinates to retrieve. If it is larger + * than the number of axes, set the excess values to~0.5 for Adobe MM + * fonts, and to~0 for TrueType GX and OpenType Font Variations. * * @output: * coords :: - * The normalized blend coordinates array (as 16.16 fractional values). + * The normalized coordinates array (as 16.16 fractional values), which + * must be allocated by the user. * * @return: * FreeType error code. 0~means success. @@ -610,8 +670,8 @@ FT_BEGIN_HEADER * For Adobe MM fonts, choose an interpolated font design by directly * setting the weight vector. * - * This function can't be used with TrueType GX or OpenType variation - * fonts. + * This function can't be used with TrueType GX or OpenType Font + * Variations. * * @inout: * face :: @@ -630,16 +690,16 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * Adobe Multiple Master fonts limit the number of designs, and thus the - * length of the weight vector to 16~elements. + * Adobe MM fonts limit the number of designs, and thus the length of the + * weight vector, to 16~elements. * * If `len` is larger than zero, this function sets the * @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field (i.e., - * @FT_IS_VARIATION will return true). If `len` is zero, this bit flag - * is unset and the weight vector array is reset to the default values. + * @FT_IS_VARIATION returns true). If `len` is zero, this bit flag is + * unset and the weight vector array is reset to the default values. * * The Adobe documentation also states that the values in the - * WeightVector array must total 1.0 +/-~0.001. In practice this does + * `WeightVector` array must total 1.0 +/-~0.001. In practice this does * not seem to be enforced, so is not enforced here, either. * * @since: @@ -659,8 +719,8 @@ FT_BEGIN_HEADER * @description: * For Adobe MM fonts, retrieve the current weight vector of the font. * - * This function can't be used with TrueType GX or OpenType variation - * fonts. + * This function can't be used with TrueType GX or OpenType Font + * Variations. * * @inout: * face :: @@ -677,14 +737,14 @@ FT_BEGIN_HEADER * * @output: * weightvector :: - * An array to be filled. + * An array to be filled; it must be allocated by the user. * * @return: * FreeType error code. 0~means success. * * @note: - * Adobe Multiple Master fonts limit the number of designs, and thus the - * length of the WeightVector to~16. + * Adobe MM fonts limit the number of designs, and thus the length of the + * weight vector, to~16 elements. * * @since: * 2.10 @@ -760,8 +820,8 @@ FT_BEGIN_HEADER * A handle to the source face. * * instance_index :: - * The index of the requested instance, starting with value 1. If set - * to value 0, FreeType switches to font access without a named + * The index of the requested instance, starting with value~1. If set + * to value~0, FreeType switches to font access without a named * instance. * * @return: @@ -771,11 +831,11 @@ FT_BEGIN_HEADER * The function uses the value of `instance_index` to set bits 16-30 of * the face's `face_index` field. It also resets any variation applied * to the font, and the @FT_FACE_FLAG_VARIATION bit of the face's - * `face_flags` field gets reset to zero (i.e., @FT_IS_VARIATION will - * return false). + * `face_flags` field gets reset to zero (i.e., @FT_IS_VARIATION returns + * false). * - * For Adobe MM fonts (which don't have named instances) this function - * simply resets the current face to the default instance. + * For Adobe MM fonts, this function resets the current face to the + * default instance. * * @since: * 2.9 @@ -794,10 +854,6 @@ FT_BEGIN_HEADER * Retrieve the index of the default named instance, to be used with * @FT_Set_Named_Instance. * - * The default instance of a variation font is that instance for which - * the nth axis coordinate is equal to `axis[n].def` (as specified in the - * @FT_MM_Var structure), with~n covering all axes. - * * FreeType synthesizes a named instance for the default instance if the * font does not contain such an entry. * @@ -813,8 +869,8 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * For Adobe MM fonts (which don't have named instances) this function - * always returns zero for `instance_index`. + * For Adobe MM fonts, this function always returns zero for + * `instance_index`. * * @since: * 2.13.1 diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h index 0ee715898f7..2669e4a03b3 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h @@ -4,7 +4,7 @@ * * FreeType modules public interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h index 6722fbf8b70..8e2ef2f01f8 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h @@ -4,7 +4,7 @@ * * FreeType module error offsets (specification). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h index 44e94b4f5bb..2545ca8486b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h @@ -5,7 +5,7 @@ * Support for the FT_Outline type used to store glyph shapes of * most scalable font formats (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h index 43bf69c202f..2c09db1683e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h @@ -4,7 +4,7 @@ * * FreeType API for possible FT_Parameter tags (specification only). * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h index dc5018a1b54..cc3102073b1 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h @@ -4,7 +4,7 @@ * * FreeType renderer modules public interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h index 4ef5c7955df..fdb89f24ccc 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h @@ -4,7 +4,7 @@ * * FreeType size objects management (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h index d5d5cd93103..99728574db6 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h index 41626dc9d7b..2c4761c768d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h @@ -4,7 +4,7 @@ * * FreeType path stroker (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h index 43081b6c330..93499a4b4f1 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h @@ -5,7 +5,7 @@ * FreeType synthesizing code for emboldening and slanting * (specification). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h index 1eacb3af398..1de9f8e603d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h @@ -4,7 +4,7 @@ * * FreeType low-level system interface definition (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h index a5299e938d4..ed7bd06a78f 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (specification). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h index 27815143a64..e207c5ebe09 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h @@ -4,7 +4,7 @@ * * FreeType simple types definitions (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h index 8865d53b389..987e704e9b0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h @@ -4,7 +4,7 @@ * * High-level 'autohint' module-specific interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h index 36b0390a5a5..26ee43bb9a9 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h @@ -4,7 +4,7 @@ * * Basic OpenType/CFF object type definitions (specification). * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h index ef2e8e7569c..62335db4834 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h @@ -5,7 +5,7 @@ * Basic OpenType/CFF type definitions and interface (specification * only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h index 876f66e2561..e6d0166d888 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h @@ -4,7 +4,7 @@ * * Compiler-specific macro definitions used internally by FreeType. * - * Copyright (C) 2020-2024 by + * Copyright (C) 2020-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -128,8 +128,8 @@ FT_BEGIN_HEADER * before a function declaration. */ - /* Visual C, mingw */ -#if defined( _WIN32 ) + /* Visual C, MinGW, Cygwin */ +#if defined( _WIN32 ) || defined( __CYGWIN__ ) #define FT_INTERNAL_FUNCTION_ATTRIBUTE /* empty */ /* gcc, clang */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h index 71128a2df90..16a732224ef 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h @@ -4,7 +4,7 @@ * * Arithmetic computations (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,17 +27,87 @@ FT_BEGIN_HEADER + /* + * The following macros have two purposes. + * + * - Tag places where overflow is expected and harmless. + * + * - Avoid run-time undefined behavior sanitizer errors. + * + * Use with care! + */ +#define ADD_INT( a, b ) \ + (FT_Int)( (FT_UInt)(a) + (FT_UInt)(b) ) +#define SUB_INT( a, b ) \ + (FT_Int)( (FT_UInt)(a) - (FT_UInt)(b) ) +#define MUL_INT( a, b ) \ + (FT_Int)( (FT_UInt)(a) * (FT_UInt)(b) ) +#define NEG_INT( a ) \ + (FT_Int)( (FT_UInt)0 - (FT_UInt)(a) ) + +#define ADD_LONG( a, b ) \ + (FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) ) +#define SUB_LONG( a, b ) \ + (FT_Long)( (FT_ULong)(a) - (FT_ULong)(b) ) +#define MUL_LONG( a, b ) \ + (FT_Long)( (FT_ULong)(a) * (FT_ULong)(b) ) +#define NEG_LONG( a ) \ + (FT_Long)( (FT_ULong)0 - (FT_ULong)(a) ) + +#define ADD_INT32( a, b ) \ + (FT_Int32)( (FT_UInt32)(a) + (FT_UInt32)(b) ) +#define SUB_INT32( a, b ) \ + (FT_Int32)( (FT_UInt32)(a) - (FT_UInt32)(b) ) +#define MUL_INT32( a, b ) \ + (FT_Int32)( (FT_UInt32)(a) * (FT_UInt32)(b) ) +#define NEG_INT32( a ) \ + (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) ) + +#ifdef FT_INT64 + +#define ADD_INT64( a, b ) \ + (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) ) +#define SUB_INT64( a, b ) \ + (FT_Int64)( (FT_UInt64)(a) - (FT_UInt64)(b) ) +#define MUL_INT64( a, b ) \ + (FT_Int64)( (FT_UInt64)(a) * (FT_UInt64)(b) ) +#define NEG_INT64( a ) \ + (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) ) + +#endif /* FT_INT64 */ + + /************************************************************************** * * FT_MulDiv() and FT_MulFix() are declared in freetype.h. * */ -#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER - /* Provide assembler fragments for performance-critical functions. */ - /* These must be defined `static __inline__' with GCC. */ +#ifdef FT_CONFIG_OPTION_INLINE_MULFIX -#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ +#ifdef FT_INT64 + + static inline FT_Long + FT_MulFix_64( FT_Long a, + FT_Long b ) + { + FT_Int64 ab = MUL_INT64( a, b ); + + + ab = ADD_INT64( ab, 0x8000 + ( ab >> 63 ) ); /* rounding phase */ + + return (FT_Long)( ab >> 16 ); + } + + +#define FT_MulFix( a, b ) FT_MulFix_64( a, b ) + +#elif !defined( FT_CONFIG_OPTION_NO_ASSEMBLER ) + /* Provide 32-bit assembler fragments for optimized FT_MulFix. */ + /* These must be defined `static __inline__' or similar. */ + +#if defined( __arm__ ) && \ + ( defined( __thumb2__ ) || !defined( __thumb__ ) ) #define FT_MULFIX_ASSEMBLER FT_MulFix_arm @@ -49,6 +119,7 @@ FT_BEGIN_HEADER { FT_Int32 t, t2; +#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ __asm { @@ -60,28 +131,8 @@ FT_BEGIN_HEADER mov a, t2, lsr #16 /* a = t2 >> 16 */ orr a, a, t, lsl #16 /* a |= t << 16 */ } - return a; - } - -#endif /* __CC_ARM || __ARMCC__ */ - - -#ifdef __GNUC__ - -#if defined( __arm__ ) && \ - ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \ - !( defined( __CC_ARM ) || defined( __ARMCC__ ) ) - -#define FT_MULFIX_ASSEMBLER FT_MulFix_arm - - /* documentation is in freetype.h */ - - static __inline__ FT_Int32 - FT_MulFix_arm( FT_Int32 a, - FT_Int32 b ) - { - FT_Int32 t, t2; +#elif defined( __GNUC__ ) __asm__ __volatile__ ( "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ @@ -98,26 +149,25 @@ FT_BEGIN_HEADER : "=r"(a), "=&r"(t2), "=&r"(t) : "r"(a), "r"(b) : "cc" ); + +#endif + return a; } -#endif /* __arm__ && */ - /* ( __thumb2__ || !__thumb__ ) && */ - /* !( __CC_ARM || __ARMCC__ ) */ - - -#if defined( __i386__ ) +#elif defined( __i386__ ) || defined( _M_IX86 ) #define FT_MULFIX_ASSEMBLER FT_MulFix_i386 /* documentation is in freetype.h */ - static __inline__ FT_Int32 + static __inline FT_Int32 FT_MulFix_i386( FT_Int32 a, FT_Int32 b ) { FT_Int32 result; +#if defined( __GNUC__ ) __asm__ __volatile__ ( "imul %%edx\n" @@ -132,27 +182,8 @@ FT_BEGIN_HEADER : "=a"(result), "=d"(b) : "a"(a), "d"(b) : "%ecx", "cc" ); - return result; - } -#endif /* i386 */ - -#endif /* __GNUC__ */ - - -#ifdef _MSC_VER /* Visual C++ */ - -#ifdef _M_IX86 - -#define FT_MULFIX_ASSEMBLER FT_MulFix_i386 - - /* documentation is in freetype.h */ - - static __inline FT_Int32 - FT_MulFix_i386( FT_Int32 a, - FT_Int32 b ) - { - FT_Int32 result; +#elif defined( _MSC_VER ) __asm { @@ -169,81 +200,21 @@ FT_BEGIN_HEADER add eax, edx mov result, eax } + +#endif + return result; } -#endif /* _M_IX86 */ +#endif /* __i386__ || _M_IX86 */ -#endif /* _MSC_VER */ - - -#if defined( __GNUC__ ) && defined( __x86_64__ ) - -#define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64 - - static __inline__ FT_Int32 - FT_MulFix_x86_64( FT_Int32 a, - FT_Int32 b ) - { - /* Temporarily disable the warning that C90 doesn't support */ - /* `long long'. */ -#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 ) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlong-long" -#endif - -#if 1 - /* Technically not an assembly fragment, but GCC does a really good */ - /* job at inlining it and generating good machine code for it. */ - long long ret, tmp; - - - ret = (long long)a * b; - tmp = ret >> 63; - ret += 0x8000 + tmp; - - return (FT_Int32)( ret >> 16 ); -#else - - /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */ - /* code from the lines below. The main issue is that `wide_a' is not */ - /* properly initialized by sign-extending `a'. Instead, the generated */ - /* machine code assumes that the register that contains `a' on input */ - /* can be used directly as a 64-bit value, which is wrong most of the */ - /* time. */ - long long wide_a = (long long)a; - long long wide_b = (long long)b; - long long result; - - - __asm__ __volatile__ ( - "imul %2, %1\n" - "mov %1, %0\n" - "sar $63, %0\n" - "lea 0x8000(%1, %0), %0\n" - "sar $16, %0\n" - : "=&r"(result), "=&r"(wide_a) - : "r"(wide_b) - : "cc" ); - - return (FT_Int32)result; -#endif - -#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 ) -#pragma GCC diagnostic pop -#endif - } - -#endif /* __GNUC__ && __x86_64__ */ - -#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ - - -#ifdef FT_CONFIG_OPTION_INLINE_MULFIX #ifdef FT_MULFIX_ASSEMBLER #define FT_MulFix( a, b ) FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) ) #endif -#endif + +#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ + +#endif /* FT_CONFIG_OPTION_INLINE_MULFIX */ /************************************************************************** @@ -278,40 +249,6 @@ FT_BEGIN_HEADER FT_Long c ); - /************************************************************************** - * - * @function: - * FT_MulAddFix - * - * @description: - * Compute `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`, where `s[n]` is - * usually a 16.16 scalar. - * - * @input: - * s :: - * The array of scalars. - * f :: - * The array of factors. - * count :: - * The number of entries in the array. - * - * @return: - * The result of `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`. - * - * @note: - * This function is currently used for the scaled delta computation of - * variation stores. It internally uses 64-bit data types when - * available, otherwise it emulates 64-bit math by using 32-bit - * operations, which produce a correct result but most likely at a slower - * performance in comparison to the implementation base on `int64_t`. - * - */ - FT_BASE( FT_Int32 ) - FT_MulAddFix( FT_Fixed* s, - FT_Int32* f, - FT_UInt count ); - - /* * A variant of FT_Matrix_Multiply which scales its result afterwards. The * idea is that both `a' and `b' are scaled by factors of 10 so that the @@ -455,6 +392,10 @@ FT_BEGIN_HEADER #define FT_MSB( x ) FT_MSB_i386( x ) +#elif defined( __CC_ARM ) + +#define FT_MSB( x ) ( 31 - __clz( x ) ) + #elif defined( __SunOS_5_11 ) #include @@ -526,55 +467,6 @@ FT_BEGIN_HEADER #define ROUND_F26DOT6( x ) ( ( (x) + 32 - ( x < 0 ) ) & -64 ) - /* - * The following macros have two purposes. - * - * - Tag places where overflow is expected and harmless. - * - * - Avoid run-time sanitizer errors. - * - * Use with care! - */ -#define ADD_INT( a, b ) \ - (FT_Int)( (FT_UInt)(a) + (FT_UInt)(b) ) -#define SUB_INT( a, b ) \ - (FT_Int)( (FT_UInt)(a) - (FT_UInt)(b) ) -#define MUL_INT( a, b ) \ - (FT_Int)( (FT_UInt)(a) * (FT_UInt)(b) ) -#define NEG_INT( a ) \ - (FT_Int)( (FT_UInt)0 - (FT_UInt)(a) ) - -#define ADD_LONG( a, b ) \ - (FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) ) -#define SUB_LONG( a, b ) \ - (FT_Long)( (FT_ULong)(a) - (FT_ULong)(b) ) -#define MUL_LONG( a, b ) \ - (FT_Long)( (FT_ULong)(a) * (FT_ULong)(b) ) -#define NEG_LONG( a ) \ - (FT_Long)( (FT_ULong)0 - (FT_ULong)(a) ) - -#define ADD_INT32( a, b ) \ - (FT_Int32)( (FT_UInt32)(a) + (FT_UInt32)(b) ) -#define SUB_INT32( a, b ) \ - (FT_Int32)( (FT_UInt32)(a) - (FT_UInt32)(b) ) -#define MUL_INT32( a, b ) \ - (FT_Int32)( (FT_UInt32)(a) * (FT_UInt32)(b) ) -#define NEG_INT32( a ) \ - (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) ) - -#ifdef FT_INT64 - -#define ADD_INT64( a, b ) \ - (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) ) -#define SUB_INT64( a, b ) \ - (FT_Int64)( (FT_UInt64)(a) - (FT_UInt64)(b) ) -#define MUL_INT64( a, b ) \ - (FT_Int64)( (FT_UInt64)(a) * (FT_UInt64)(b) ) -#define NEG_INT64( a ) \ - (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) ) - -#endif /* FT_INT64 */ - FT_END_HEADER diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h index d7fa8dc93cf..d7facf40d12 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h @@ -4,7 +4,7 @@ * * Debugging and logging component (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h index 5609b3ef12b..24be4dad36b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h @@ -4,7 +4,7 @@ * * FreeType internal font driver interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h index f1c155b162c..8f2a54c015b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h @@ -4,7 +4,7 @@ * * The FreeType glyph loader (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fthash.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fthash.h index 622ec76bb9a..642d21e21c6 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fthash.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fthash.h @@ -117,6 +117,18 @@ FT_BEGIN_HEADER FT_Hash hash, FT_Memory memory ); + FT_Error + ft_hash_str_insert_no_overwrite( const char* key, + size_t data, + FT_Hash hash, + FT_Memory memory ); + + FT_Error + ft_hash_num_insert_no_overwrite( FT_Int num, + size_t data, + FT_Hash hash, + FT_Memory memory ); + size_t* ft_hash_str_lookup( const char* key, FT_Hash hash ); @@ -125,6 +137,17 @@ FT_BEGIN_HEADER ft_hash_num_lookup( FT_Int num, FT_Hash hash ); + FT_Bool + ft_hash_num_iterator( FT_UInt *idx, + FT_Int *key, + size_t *value, + FT_Hash hash ); + + FT_Bool + ft_hash_str_iterator( FT_UInt *idx, + const char* *key, + size_t *value, + FT_Hash hash ); FT_END_HEADER diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h index 4e05a29f13a..c75c33f2895 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h @@ -4,7 +4,7 @@ * * The FreeType memory management macros (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h index 8449e7a010d..be3747bbf94 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h @@ -5,7 +5,7 @@ * OpenType Variations type definitions for internal use * with the multi-masters service (specification). * - * Copyright (C) 2022-2024 by + * Copyright (C) 2022-2025 by * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and * Dominik Röttsches. * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h index a1e93298fdb..3db2fe28ffd 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h @@ -4,7 +4,7 @@ * * The FreeType private base classes (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -275,6 +275,28 @@ FT_BEGIN_HEADER FT_GlyphSlot slot, FT_Render_Mode mode ); + + /************************************************************************** + * + * @Function: + * find_unicode_charmap + * + * @Description: + * This function finds a Unicode charmap, if there is one. And if there + * is more than one, it tries to favour the more extensive one, i.e., one + * that supports UCS-4 against those which are limited to the BMP (UCS-2 + * encoding.) + * + * If a unicode charmap is found, `face->charmap` is set to it. + * + * This function is called from `open_face`, from `FT_Select_Charmap(..., + * FT_ENCODING_UNICODE)`, and also from `afadjust.c` in the 'autofit' + * module. + */ + FT_BASE( FT_Error ) + find_unicode_charmap( FT_Face face ); + + #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap, @@ -498,9 +520,9 @@ FT_BEGIN_HEADER */ typedef struct FT_ModuleRec_ { - FT_Module_Class* clazz; - FT_Library library; - FT_Memory memory; + const FT_Module_Class* clazz; + FT_Library library; + FT_Memory memory; } FT_ModuleRec; diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h index 4f11aa16ba1..18a954d22f5 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h @@ -4,7 +4,7 @@ * * Get and set properties of PostScript drivers (specification). * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h index 05c1d6c48b5..e077f98bfb9 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (specification). * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * Masatake YAMATO and Redhat K.K. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h index 8c35dbd7139..ce11bba19b2 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h @@ -4,7 +4,7 @@ * * The FreeType services (specification only). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h index fd52f767ef7..20c1dd7c4b0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h @@ -4,7 +4,7 @@ * * Stream handling (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h index 42595a29ff3..3fd592800e2 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h @@ -4,7 +4,7 @@ * * Tracing handling (specification only). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -19,7 +19,7 @@ /* definitions of trace levels for FreeType 2 */ /* the maximum string length (if the argument to `FT_TRACE_DEF` */ - /* gets used as a string) plus one charachter for ':' plus */ + /* gets used as a string) plus one character for ':' plus */ /* another one for the trace level */ #define FT_MAX_TRACE_LEVEL_LENGTH (9 + 1 + 1) @@ -159,6 +159,7 @@ FT_TRACE_DEF( gxvprop ) FT_TRACE_DEF( gxvtrak ) /* autofit components */ +FT_TRACE_DEF( afadjust ) FT_TRACE_DEF( afcjk ) FT_TRACE_DEF( afglobal ) FT_TRACE_DEF( afhints ) diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h index a1312f2aba6..03a726c82cb 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h @@ -4,7 +4,7 @@ * * FreeType validation support (specification). * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h index 745d2cb56b7..344be0f19a7 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h @@ -5,7 +5,7 @@ * Auxiliary functions and data structures related to PostScript fonts * (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h index dba6c7303fd..96c5d84f058 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h @@ -6,7 +6,7 @@ * recorders (specification only). These are used to support native * T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers. * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h index 89e9c2e5de8..5bd51da23f4 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h @@ -4,7 +4,7 @@ * * The FreeType BDF services (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h index 3cb483c344f..c97bf84fb2e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h @@ -4,7 +4,7 @@ * * The FreeType CFF tables loader service (specification). * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h index 8362cb8724d..748a8caf887 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h @@ -4,7 +4,7 @@ * * The FreeType CID font services (specification). * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h index 6b837e79fcd..690fdc2a24f 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h @@ -4,7 +4,7 @@ * * The FreeType font format service (specification only). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h index 6126ec9ada4..7128d6f3d7a 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h @@ -4,7 +4,7 @@ * * The FreeType glyph dictionary services (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h index 29cf5528189..1ca3e0a031b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h @@ -4,7 +4,7 @@ * * FreeType API for validating TrueTypeGX/AAT tables (specification). * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * Masatake YAMATO, Red Hat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h index ac1bc30c412..8a3d59bec6d 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h @@ -4,7 +4,7 @@ * * The FreeType Kerning service (specification). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h index 8b3563b25ca..4dde3a8151a 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h @@ -4,7 +4,7 @@ * * The FreeType services for metrics variations (specification). * - * Copyright (C) 2016-2024 by + * Copyright (C) 2016-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -77,7 +77,7 @@ FT_BEGIN_HEADER typedef void (*FT_Metrics_Adjust_Func)( FT_Face face ); - typedef FT_Error + typedef void (*FT_Size_Reset_Func)( FT_Size size ); diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h index 5288fadf375..9be133e2db0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h @@ -4,7 +4,7 @@ * * The FreeType Multiple Masters and GX var services (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h index 7aea7ec11f0..933e5de98da 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h @@ -4,7 +4,7 @@ * * The FreeType OpenType validation service (specification). * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h index b2fac6d086b..c81b6a68a8b 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h @@ -4,7 +4,7 @@ * * Internal PFR service functions (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h index d19f3adc6d5..33864ebc344 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h @@ -4,7 +4,7 @@ * * The FreeType PostScript name services (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h index ba39c0dd4da..0eb79c885d8 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h @@ -4,7 +4,7 @@ * * The FreeType property service (specification). * - * Copyright (C) 2012-2024 by + * Copyright (C) 2012-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h index d4908ee41aa..8f85d12157c 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h @@ -4,7 +4,7 @@ * * The FreeType PostScript charmap service (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h index 2aadcdd02a1..83de04478df 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h @@ -4,7 +4,7 @@ * * The FreeType PostScript info service (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h index 9e0f4ff202e..9bf5e3473c4 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h @@ -4,7 +4,7 @@ * * The FreeType SFNT table loading service (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h index 250886bcc5d..fc9b0aeb8e3 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h @@ -4,7 +4,7 @@ * * The FreeType TrueType/sfnt cmap extra information service. * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * Masatake YAMATO, Redhat K.K., * David Turner, Robert Wilhelm, and Werner Lemberg. * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h index 14967529a9a..979e9ea102e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h @@ -4,7 +4,7 @@ * * The FreeType TrueType engine query service (specification). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h index f190b3985d0..e4f54c10037 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h @@ -4,7 +4,7 @@ * * The FreeType TrueType glyph service. * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h index 49f3fb7f775..ff887ffdc03 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h @@ -4,7 +4,7 @@ * * The FreeType Windows FNT/FONT service (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h index 35e4e73af02..adba2178877 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h @@ -4,7 +4,7 @@ * * High-level 'sfnt' driver interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -612,7 +612,7 @@ FT_BEGIN_HEADER * * @return: * Value~1 if a ClipBox is found. If no clip box is found or an - * error occured, value~0 is returned. + * error occurred, value~0 is returned. */ typedef FT_Bool ( *TT_Get_Color_Glyph_ClipBox_Func )( TT_Face face, @@ -707,7 +707,7 @@ FT_BEGIN_HEADER * * @return: * Value~1 if everything is OK. Value~0 if no details can be found for - * this paint or any other error occured. + * this paint or any other error occurred. */ typedef FT_Bool ( *TT_Get_Paint_Func )( TT_Face face, @@ -808,7 +808,7 @@ FT_BEGIN_HEADER * corresponding (1,0) Apple entry. * * @return: - * 1 if there is either a win or apple entry (or both), 0 otheriwse. + * 1 if there is either a win or apple entry (or both), 0 otherwise. */ typedef FT_Bool (*TT_Get_Name_ID_Func)( TT_Face face, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h index 68c99efb10a..20c73b2fbd2 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h @@ -4,7 +4,7 @@ * * Interface of ot-svg module (specification only). * - * Copyright (C) 2022-2024 by + * Copyright (C) 2022-2025 by * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h index 1821ae5cc83..5b26e4620d0 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h @@ -5,7 +5,7 @@ * Basic Type1/Type2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h index 7053e656a7e..d0e5eee89bc 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType type definitions and interface (specification * only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -930,8 +930,8 @@ FT_BEGIN_HEADER * resolution and scaling independent parts of a TrueType font resource. * * @note: - * The TT_Face structure is also used as a 'parent class' for the - * OpenType-CFF class (T2_Face). + * The TT_Face structure is also used for CFF support; see file + * `cffotypes.h`. */ typedef struct TT_FaceRec_* TT_Face; @@ -1276,10 +1276,6 @@ FT_BEGIN_HEADER * * If varied by the `CVAR' table, non-integer values are possible. * - * interpreter :: - * A pointer to the TrueType bytecode interpreters field is also used - * to hook the debugger in 'ttdebug'. - * * extra :: * Reserved for third-party font drivers. * @@ -1521,10 +1517,6 @@ FT_BEGIN_HEADER FT_ULong cvt_size; FT_Int32* cvt; - /* A pointer to the bytecode interpreter to use. This is also */ - /* used to hook the debugger for the `ttdebug' utility. */ - TT_Interpreter interpreter; - /************************************************************************ * @@ -1582,11 +1574,6 @@ FT_BEGIN_HEADER FT_UInt32 kern_avail_bits; FT_UInt32 kern_order_bits; -#ifdef TT_CONFIG_OPTION_GPOS_KERNING - FT_Byte* gpos_table; - FT_Bool gpos_kerning_available; -#endif - #ifdef TT_CONFIG_OPTION_BDF TT_BDFRec bdf; #endif /* TT_CONFIG_OPTION_BDF */ @@ -1608,6 +1595,15 @@ FT_BEGIN_HEADER /* since 2.12 */ void* svg; +#ifdef TT_CONFIG_OPTION_GPOS_KERNING + /* since 2.13.3 */ + FT_Byte* gpos_table; + /* since 2.14 */ + /* This is actually an array of GPOS lookup subtables. */ + FT_UInt32* gpos_lookups_kerning; + FT_UInt num_gpos_lookups_kerning; +#endif + } TT_FaceRec; @@ -1621,15 +1617,6 @@ FT_BEGIN_HEADER * coordinates. * * @fields: - * memory :: - * A handle to the memory manager. - * - * max_points :: - * The maximum size in points of the zone. - * - * max_contours :: - * Max size in links contours of the zone. - * * n_points :: * The current number of points in the zone. * @@ -1653,9 +1640,6 @@ FT_BEGIN_HEADER */ typedef struct TT_GlyphZoneRec_ { - FT_Memory memory; - FT_UShort max_points; - FT_UShort max_contours; FT_UShort n_points; /* number of points in zone */ FT_UShort n_contours; /* number of contours */ @@ -1714,7 +1698,6 @@ FT_BEGIN_HEADER TT_GlyphZoneRec zone; TT_ExecContext exec; - FT_Byte* instructions; FT_ULong ins_pos; /* for possible extensibility in other formats */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h index 4a169d12f57..7d5b7df0fa1 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h @@ -5,7 +5,7 @@ * Basic WOFF/WOFF2 type definitions and interface (specification * only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h index 9d356938cc7..326bbcd0153 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h @@ -4,7 +4,7 @@ * * Interface for OT-SVG support related things (specification). * - * Copyright (C) 2022-2024 by + * Copyright (C) 2022-2025 by * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h index fbd558aa34d..fc3c1706de5 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h @@ -5,7 +5,7 @@ * Basic Type 1/Type 2 tables definitions and interface (specification * only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h index d5d470e380f..3ef61091cc9 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h @@ -4,7 +4,7 @@ * * TrueType name ID definitions (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -436,7 +436,7 @@ FT_BEGIN_HEADER * * The canonical source for Microsoft's IDs is * - * https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings , + * https://learn.microsoft.com/windows/win32/intl/language-identifier-constants-and-strings , * * however, we only provide macros for language identifiers present in * the OpenType specification: Microsoft has abandoned the concept of @@ -847,113 +847,113 @@ FT_BEGIN_HEADER /* --------------- */ /* Bit 0 Basic Latin */ -#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ +#define TT_UCR_BASIC_LATIN (1UL << 0) /* U+0020-U+007E */ /* Bit 1 C1 Controls and Latin-1 Supplement */ -#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ +#define TT_UCR_LATIN1_SUPPLEMENT (1UL << 1) /* U+0080-U+00FF */ /* Bit 2 Latin Extended-A */ -#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ +#define TT_UCR_LATIN_EXTENDED_A (1UL << 2) /* U+0100-U+017F */ /* Bit 3 Latin Extended-B */ -#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ +#define TT_UCR_LATIN_EXTENDED_B (1UL << 3) /* U+0180-U+024F */ /* Bit 4 IPA Extensions */ /* Phonetic Extensions */ /* Phonetic Extensions Supplement */ -#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ +#define TT_UCR_IPA_EXTENSIONS (1UL << 4) /* U+0250-U+02AF */ /* U+1D00-U+1D7F */ /* U+1D80-U+1DBF */ /* Bit 5 Spacing Modifier Letters */ /* Modifier Tone Letters */ -#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ +#define TT_UCR_SPACING_MODIFIER (1UL << 5) /* U+02B0-U+02FF */ /* U+A700-U+A71F */ /* Bit 6 Combining Diacritical Marks */ /* Combining Diacritical Marks Supplement */ -#define TT_UCR_COMBINING_DIACRITICAL_MARKS (1L << 6) /* U+0300-U+036F */ +#define TT_UCR_COMBINING_DIACRITICAL_MARKS (1UL << 6) /* U+0300-U+036F */ /* U+1DC0-U+1DFF */ /* Bit 7 Greek and Coptic */ -#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ +#define TT_UCR_GREEK (1UL << 7) /* U+0370-U+03FF */ /* Bit 8 Coptic */ -#define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */ +#define TT_UCR_COPTIC (1UL << 8) /* U+2C80-U+2CFF */ /* Bit 9 Cyrillic */ /* Cyrillic Supplement */ /* Cyrillic Extended-A */ /* Cyrillic Extended-B */ -#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ +#define TT_UCR_CYRILLIC (1UL << 9) /* U+0400-U+04FF */ /* U+0500-U+052F */ /* U+2DE0-U+2DFF */ /* U+A640-U+A69F */ /* Bit 10 Armenian */ -#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ +#define TT_UCR_ARMENIAN (1UL << 10) /* U+0530-U+058F */ /* Bit 11 Hebrew */ -#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ +#define TT_UCR_HEBREW (1UL << 11) /* U+0590-U+05FF */ /* Bit 12 Vai */ -#define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */ +#define TT_UCR_VAI (1UL << 12) /* U+A500-U+A63F */ /* Bit 13 Arabic */ /* Arabic Supplement */ -#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ +#define TT_UCR_ARABIC (1UL << 13) /* U+0600-U+06FF */ /* U+0750-U+077F */ /* Bit 14 NKo */ -#define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */ +#define TT_UCR_NKO (1UL << 14) /* U+07C0-U+07FF */ /* Bit 15 Devanagari */ -#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ - /* Bit 16 Bengali */ -#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ +#define TT_UCR_DEVANAGARI (1UL << 15) /* U+0900-U+097F */ + /* Bit 16 Bangla (Bengali) */ +#define TT_UCR_BENGALI (1UL << 16) /* U+0980-U+09FF */ /* Bit 17 Gurmukhi */ -#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ +#define TT_UCR_GURMUKHI (1UL << 17) /* U+0A00-U+0A7F */ /* Bit 18 Gujarati */ -#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ - /* Bit 19 Oriya */ -#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ +#define TT_UCR_GUJARATI (1UL << 18) /* U+0A80-U+0AFF */ + /* Bit 19 Oriya (Odia) */ +#define TT_UCR_ORIYA (1UL << 19) /* U+0B00-U+0B7F */ /* Bit 20 Tamil */ -#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ +#define TT_UCR_TAMIL (1UL << 20) /* U+0B80-U+0BFF */ /* Bit 21 Telugu */ -#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ +#define TT_UCR_TELUGU (1UL << 21) /* U+0C00-U+0C7F */ /* Bit 22 Kannada */ -#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ +#define TT_UCR_KANNADA (1UL << 22) /* U+0C80-U+0CFF */ /* Bit 23 Malayalam */ -#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ +#define TT_UCR_MALAYALAM (1UL << 23) /* U+0D00-U+0D7F */ /* Bit 24 Thai */ -#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ +#define TT_UCR_THAI (1UL << 24) /* U+0E00-U+0E7F */ /* Bit 25 Lao */ -#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ +#define TT_UCR_LAO (1UL << 25) /* U+0E80-U+0EFF */ /* Bit 26 Georgian */ /* Georgian Supplement */ -#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ +#define TT_UCR_GEORGIAN (1UL << 26) /* U+10A0-U+10FF */ /* U+2D00-U+2D2F */ /* Bit 27 Balinese */ -#define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */ +#define TT_UCR_BALINESE (1UL << 27) /* U+1B00-U+1B7F */ /* Bit 28 Hangul Jamo */ -#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ +#define TT_UCR_HANGUL_JAMO (1UL << 28) /* U+1100-U+11FF */ /* Bit 29 Latin Extended Additional */ /* Latin Extended-C */ /* Latin Extended-D */ -#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1UL << 29) /* U+1E00-U+1EFF */ /* U+2C60-U+2C7F */ /* U+A720-U+A7FF */ /* Bit 30 Greek Extended */ -#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ +#define TT_UCR_GREEK_EXTENDED (1UL << 30) /* U+1F00-U+1FFF */ /* Bit 31 General Punctuation */ /* Supplemental Punctuation */ -#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ +#define TT_UCR_GENERAL_PUNCTUATION (1UL << 31) /* U+2000-U+206F */ /* U+2E00-U+2E7F */ /* ulUnicodeRange2 */ /* --------------- */ /* Bit 32 Superscripts And Subscripts */ -#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1UL << 0) /* U+2070-U+209F */ /* Bit 33 Currency Symbols */ -#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ +#define TT_UCR_CURRENCY_SYMBOLS (1UL << 1) /* U+20A0-U+20CF */ /* Bit 34 Combining Diacritical Marks For Symbols */ #define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ - (1L << 2) /* U+20D0-U+20FF */ + (1UL << 2) /* U+20D0-U+20FF */ /* Bit 35 Letterlike Symbols */ -#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1UL << 3) /* U+2100-U+214F */ /* Bit 36 Number Forms */ -#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ +#define TT_UCR_NUMBER_FORMS (1UL << 4) /* U+2150-U+218F */ /* Bit 37 Arrows */ /* Supplemental Arrows-A */ /* Supplemental Arrows-B */ /* Miscellaneous Symbols and Arrows */ -#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ +#define TT_UCR_ARROWS (1UL << 5) /* U+2190-U+21FF */ /* U+27F0-U+27FF */ /* U+2900-U+297F */ /* U+2B00-U+2BFF */ @@ -961,52 +961,52 @@ FT_BEGIN_HEADER /* Supplemental Mathematical Operators */ /* Miscellaneous Mathematical Symbols-A */ /* Miscellaneous Mathematical Symbols-B */ -#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1UL << 6) /* U+2200-U+22FF */ /* U+2A00-U+2AFF */ /* U+27C0-U+27EF */ /* U+2980-U+29FF */ /* Bit 39 Miscellaneous Technical */ -#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1UL << 7) /* U+2300-U+23FF */ /* Bit 40 Control Pictures */ -#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ +#define TT_UCR_CONTROL_PICTURES (1UL << 8) /* U+2400-U+243F */ /* Bit 41 Optical Character Recognition */ -#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ +#define TT_UCR_OCR (1UL << 9) /* U+2440-U+245F */ /* Bit 42 Enclosed Alphanumerics */ -#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1UL << 10) /* U+2460-U+24FF */ /* Bit 43 Box Drawing */ -#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ +#define TT_UCR_BOX_DRAWING (1UL << 11) /* U+2500-U+257F */ /* Bit 44 Block Elements */ -#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ +#define TT_UCR_BLOCK_ELEMENTS (1UL << 12) /* U+2580-U+259F */ /* Bit 45 Geometric Shapes */ -#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ +#define TT_UCR_GEOMETRIC_SHAPES (1UL << 13) /* U+25A0-U+25FF */ /* Bit 46 Miscellaneous Symbols */ -#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1UL << 14) /* U+2600-U+26FF */ /* Bit 47 Dingbats */ -#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ +#define TT_UCR_DINGBATS (1UL << 15) /* U+2700-U+27BF */ /* Bit 48 CJK Symbols and Punctuation */ -#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ +#define TT_UCR_CJK_SYMBOLS (1UL << 16) /* U+3000-U+303F */ /* Bit 49 Hiragana */ -#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ +#define TT_UCR_HIRAGANA (1UL << 17) /* U+3040-U+309F */ /* Bit 50 Katakana */ /* Katakana Phonetic Extensions */ -#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ +#define TT_UCR_KATAKANA (1UL << 18) /* U+30A0-U+30FF */ /* U+31F0-U+31FF */ /* Bit 51 Bopomofo */ /* Bopomofo Extended */ -#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ +#define TT_UCR_BOPOMOFO (1UL << 19) /* U+3100-U+312F */ /* U+31A0-U+31BF */ /* Bit 52 Hangul Compatibility Jamo */ -#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1UL << 20) /* U+3130-U+318F */ /* Bit 53 Phags-Pa */ -#define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */ -#define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */ -#define TT_UCR_PHAGSPA +#define TT_UCR_PHAGSPA (1UL << 21) /* U+A840-U+A87F */ +#define TT_UCR_KANBUN TT_UCR_PHAGSPA /* deprecated */ +#define TT_UCR_CJK_MISC TT_UCR_PHAGSPA /* deprecated */ /* Bit 54 Enclosed CJK Letters and Months */ -#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1UL << 22) /* U+3200-U+32FF */ /* Bit 55 CJK Compatibility */ -#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ +#define TT_UCR_CJK_COMPATIBILITY (1UL << 23) /* U+3300-U+33FF */ /* Bit 56 Hangul Syllables */ -#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ +#define TT_UCR_HANGUL (1UL << 24) /* U+AC00-U+D7A3 */ /* Bit 57 High Surrogates */ /* High Private Use Surrogates */ /* Low Surrogates */ @@ -1017,12 +1017,12 @@ FT_BEGIN_HEADER /* Basic Multilingual Plane that is */ /* supported by this font. So it really */ /* means >= U+10000. */ -#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ +#define TT_UCR_SURROGATES (1UL << 25) /* U+D800-U+DB7F */ /* U+DB80-U+DBFF */ /* U+DC00-U+DFFF */ #define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES /* Bit 58 Phoenician */ -#define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/ +#define TT_UCR_PHOENICIAN (1UL << 26) /*U+10900-U+1091F*/ /* Bit 59 CJK Unified Ideographs */ /* CJK Radicals Supplement */ /* Kangxi Radicals */ @@ -1030,7 +1030,7 @@ FT_BEGIN_HEADER /* CJK Unified Ideographs Extension A */ /* CJK Unified Ideographs Extension B */ /* Kanbun */ -#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1UL << 27) /* U+4E00-U+9FFF */ /* U+2E80-U+2EFF */ /* U+2F00-U+2FDF */ /* U+2FF0-U+2FFF */ @@ -1038,178 +1038,178 @@ FT_BEGIN_HEADER /*U+20000-U+2A6DF*/ /* U+3190-U+319F */ /* Bit 60 Private Use */ -#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ +#define TT_UCR_PRIVATE_USE (1UL << 28) /* U+E000-U+F8FF */ /* Bit 61 CJK Strokes */ /* CJK Compatibility Ideographs */ /* CJK Compatibility Ideographs Supplement */ -#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1UL << 29) /* U+31C0-U+31EF */ /* U+F900-U+FAFF */ /*U+2F800-U+2FA1F*/ /* Bit 62 Alphabetic Presentation Forms */ -#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1UL << 30) /* U+FB00-U+FB4F */ /* Bit 63 Arabic Presentation Forms-A */ -#define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1L << 31) /* U+FB50-U+FDFF */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1UL << 31) /* U+FB50-U+FDFF */ /* ulUnicodeRange3 */ /* --------------- */ /* Bit 64 Combining Half Marks */ -#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ +#define TT_UCR_COMBINING_HALF_MARKS (1UL << 0) /* U+FE20-U+FE2F */ /* Bit 65 Vertical forms */ /* CJK Compatibility Forms */ -#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1UL << 1) /* U+FE10-U+FE1F */ /* U+FE30-U+FE4F */ /* Bit 66 Small Form Variants */ -#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ +#define TT_UCR_SMALL_FORM_VARIANTS (1UL << 2) /* U+FE50-U+FE6F */ /* Bit 67 Arabic Presentation Forms-B */ -#define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1L << 3) /* U+FE70-U+FEFE */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1UL << 3) /* U+FE70-U+FEFF */ /* Bit 68 Halfwidth and Fullwidth Forms */ -#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1UL << 4) /* U+FF00-U+FFEF */ /* Bit 69 Specials */ -#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ +#define TT_UCR_SPECIALS (1UL << 5) /* U+FFF0-U+FFFF */ /* Bit 70 Tibetan */ -#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */ +#define TT_UCR_TIBETAN (1UL << 6) /* U+0F00-U+0FFF */ /* Bit 71 Syriac */ -#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ +#define TT_UCR_SYRIAC (1UL << 7) /* U+0700-U+074F */ /* Bit 72 Thaana */ -#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ +#define TT_UCR_THAANA (1UL << 8) /* U+0780-U+07BF */ /* Bit 73 Sinhala */ -#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ +#define TT_UCR_SINHALA (1UL << 9) /* U+0D80-U+0DFF */ /* Bit 74 Myanmar */ -#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ +#define TT_UCR_MYANMAR (1UL << 10) /* U+1000-U+109F */ /* Bit 75 Ethiopic */ /* Ethiopic Supplement */ /* Ethiopic Extended */ -#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */ +#define TT_UCR_ETHIOPIC (1UL << 11) /* U+1200-U+137F */ /* U+1380-U+139F */ /* U+2D80-U+2DDF */ /* Bit 76 Cherokee */ -#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ +#define TT_UCR_CHEROKEE (1UL << 12) /* U+13A0-U+13FF */ /* Bit 77 Unified Canadian Aboriginal Syllabics */ -#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */ +#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1UL << 13) /* U+1400-U+167F */ /* Bit 78 Ogham */ -#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ +#define TT_UCR_OGHAM (1UL << 14) /* U+1680-U+169F */ /* Bit 79 Runic */ -#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ +#define TT_UCR_RUNIC (1UL << 15) /* U+16A0-U+16FF */ /* Bit 80 Khmer */ /* Khmer Symbols */ -#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ +#define TT_UCR_KHMER (1UL << 16) /* U+1780-U+17FF */ /* U+19E0-U+19FF */ /* Bit 81 Mongolian */ -#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ +#define TT_UCR_MONGOLIAN (1UL << 17) /* U+1800-U+18AF */ /* Bit 82 Braille Patterns */ -#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ +#define TT_UCR_BRAILLE (1UL << 18) /* U+2800-U+28FF */ /* Bit 83 Yi Syllables */ /* Yi Radicals */ -#define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */ +#define TT_UCR_YI (1UL << 19) /* U+A000-U+A48F */ /* U+A490-U+A4CF */ /* Bit 84 Tagalog */ /* Hanunoo */ /* Buhid */ /* Tagbanwa */ -#define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */ +#define TT_UCR_PHILIPPINE (1UL << 20) /* U+1700-U+171F */ /* U+1720-U+173F */ /* U+1740-U+175F */ /* U+1760-U+177F */ /* Bit 85 Old Italic */ -#define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/ +#define TT_UCR_OLD_ITALIC (1UL << 21) /*U+10300-U+1032F*/ /* Bit 86 Gothic */ -#define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/ +#define TT_UCR_GOTHIC (1UL << 22) /*U+10330-U+1034F*/ /* Bit 87 Deseret */ -#define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/ +#define TT_UCR_DESERET (1UL << 23) /*U+10400-U+1044F*/ /* Bit 88 Byzantine Musical Symbols */ /* Musical Symbols */ /* Ancient Greek Musical Notation */ -#define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/ +#define TT_UCR_MUSICAL_SYMBOLS (1UL << 24) /*U+1D000-U+1D0FF*/ /*U+1D100-U+1D1FF*/ /*U+1D200-U+1D24F*/ /* Bit 89 Mathematical Alphanumeric Symbols */ -#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/ +#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1UL << 25) /*U+1D400-U+1D7FF*/ /* Bit 90 Private Use (plane 15) */ /* Private Use (plane 16) */ -#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/ +#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1UL << 26) /*U+F0000-U+FFFFD*/ /*U+100000-U+10FFFD*/ /* Bit 91 Variation Selectors */ /* Variation Selectors Supplement */ -#define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */ +#define TT_UCR_VARIATION_SELECTORS (1UL << 27) /* U+FE00-U+FE0F */ /*U+E0100-U+E01EF*/ /* Bit 92 Tags */ -#define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/ +#define TT_UCR_TAGS (1UL << 28) /*U+E0000-U+E007F*/ /* Bit 93 Limbu */ -#define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */ +#define TT_UCR_LIMBU (1UL << 29) /* U+1900-U+194F */ /* Bit 94 Tai Le */ -#define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */ +#define TT_UCR_TAI_LE (1UL << 30) /* U+1950-U+197F */ /* Bit 95 New Tai Lue */ -#define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */ +#define TT_UCR_NEW_TAI_LUE (1UL << 31) /* U+1980-U+19DF */ /* ulUnicodeRange4 */ /* --------------- */ /* Bit 96 Buginese */ -#define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */ +#define TT_UCR_BUGINESE (1UL << 0) /* U+1A00-U+1A1F */ /* Bit 97 Glagolitic */ -#define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */ +#define TT_UCR_GLAGOLITIC (1UL << 1) /* U+2C00-U+2C5F */ /* Bit 98 Tifinagh */ -#define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */ +#define TT_UCR_TIFINAGH (1UL << 2) /* U+2D30-U+2D7F */ /* Bit 99 Yijing Hexagram Symbols */ -#define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */ +#define TT_UCR_YIJING (1UL << 3) /* U+4DC0-U+4DFF */ /* Bit 100 Syloti Nagri */ -#define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */ +#define TT_UCR_SYLOTI_NAGRI (1UL << 4) /* U+A800-U+A82F */ /* Bit 101 Linear B Syllabary */ /* Linear B Ideograms */ /* Aegean Numbers */ -#define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/ +#define TT_UCR_LINEAR_B (1UL << 5) /*U+10000-U+1007F*/ /*U+10080-U+100FF*/ /*U+10100-U+1013F*/ /* Bit 102 Ancient Greek Numbers */ -#define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/ +#define TT_UCR_ANCIENT_GREEK_NUMBERS (1UL << 6) /*U+10140-U+1018F*/ /* Bit 103 Ugaritic */ -#define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/ +#define TT_UCR_UGARITIC (1UL << 7) /*U+10380-U+1039F*/ /* Bit 104 Old Persian */ -#define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/ +#define TT_UCR_OLD_PERSIAN (1UL << 8) /*U+103A0-U+103DF*/ /* Bit 105 Shavian */ -#define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/ +#define TT_UCR_SHAVIAN (1UL << 9) /*U+10450-U+1047F*/ /* Bit 106 Osmanya */ -#define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/ +#define TT_UCR_OSMANYA (1UL << 10) /*U+10480-U+104AF*/ /* Bit 107 Cypriot Syllabary */ -#define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/ +#define TT_UCR_CYPRIOT_SYLLABARY (1UL << 11) /*U+10800-U+1083F*/ /* Bit 108 Kharoshthi */ -#define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/ +#define TT_UCR_KHAROSHTHI (1UL << 12) /*U+10A00-U+10A5F*/ /* Bit 109 Tai Xuan Jing Symbols */ -#define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/ +#define TT_UCR_TAI_XUAN_JING (1UL << 13) /*U+1D300-U+1D35F*/ /* Bit 110 Cuneiform */ /* Cuneiform Numbers and Punctuation */ -#define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/ +#define TT_UCR_CUNEIFORM (1UL << 14) /*U+12000-U+123FF*/ /*U+12400-U+1247F*/ /* Bit 111 Counting Rod Numerals */ -#define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/ +#define TT_UCR_COUNTING_ROD_NUMERALS (1UL << 15) /*U+1D360-U+1D37F*/ /* Bit 112 Sundanese */ -#define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */ +#define TT_UCR_SUNDANESE (1UL << 16) /* U+1B80-U+1BBF */ /* Bit 113 Lepcha */ -#define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */ +#define TT_UCR_LEPCHA (1UL << 17) /* U+1C00-U+1C4F */ /* Bit 114 Ol Chiki */ -#define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */ +#define TT_UCR_OL_CHIKI (1UL << 18) /* U+1C50-U+1C7F */ /* Bit 115 Saurashtra */ -#define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */ +#define TT_UCR_SAURASHTRA (1UL << 19) /* U+A880-U+A8DF */ /* Bit 116 Kayah Li */ -#define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */ +#define TT_UCR_KAYAH_LI (1UL << 20) /* U+A900-U+A92F */ /* Bit 117 Rejang */ -#define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */ +#define TT_UCR_REJANG (1UL << 21) /* U+A930-U+A95F */ /* Bit 118 Cham */ -#define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */ +#define TT_UCR_CHAM (1UL << 22) /* U+AA00-U+AA5F */ /* Bit 119 Ancient Symbols */ -#define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/ +#define TT_UCR_ANCIENT_SYMBOLS (1UL << 23) /*U+10190-U+101CF*/ /* Bit 120 Phaistos Disc */ -#define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/ +#define TT_UCR_PHAISTOS_DISC (1UL << 24) /*U+101D0-U+101FF*/ /* Bit 121 Carian */ /* Lycian */ /* Lydian */ -#define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/ +#define TT_UCR_OLD_ANATOLIAN (1UL << 25) /*U+102A0-U+102DF*/ /*U+10280-U+1029F*/ /*U+10920-U+1093F*/ /* Bit 122 Domino Tiles */ /* Mahjong Tiles */ -#define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/ +#define TT_UCR_GAME_TILES (1UL << 26) /*U+1F030-U+1F09F*/ /*U+1F000-U+1F02F*/ /* Bit 123-127 Reserved for process-internal usage */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h index 2cf0ff1bc61..aa4336435d9 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h @@ -5,7 +5,7 @@ * Basic SFNT/TrueType tables definitions and interface * (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -192,7 +192,7 @@ FT_BEGIN_HEADER * A pointer into the 'hmtx' table. * * @note: - * For an OpenType variation font, the values of the following fields can + * For OpenType Font Variations, the values of the following fields can * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if * the font contains an 'MVAR' table: `caret_Slope_Rise`, * `caret_Slope_Run`, and `caret_Offset`. @@ -310,7 +310,7 @@ FT_BEGIN_HEADER * A pointer into the 'vmtx' table. * * @note: - * For an OpenType variation font, the values of the following fields can + * For OpenType Font Variations, the values of the following fields can * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if * the font contains an 'MVAR' table: `Ascender`, `Descender`, * `Line_Gap`, `caret_Slope_Rise`, `caret_Slope_Run`, and `caret_Offset`. @@ -359,7 +359,7 @@ FT_BEGIN_HEADER * table. In this case, the `version` field is always set to 0xFFFF. * * @note: - * For an OpenType variation font, the values of the following fields can + * For OpenType Font Variations, the values of the following fields can * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if * the font contains an 'MVAR' table: `sCapHeight`, `sTypoAscender`, * `sTypoDescender`, `sTypoLineGap`, `sxHeight`, `usWinAscent`, @@ -442,7 +442,7 @@ FT_BEGIN_HEADER * them. * * @note: - * For an OpenType variation font, the values of the following fields can + * For OpenType Font Variations, the values of the following fields can * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if * the font contains an 'MVAR' table: `underlinePosition` and * `underlineThickness`. @@ -705,6 +705,9 @@ FT_BEGIN_HEADER * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new * one with @FT_MAKE_TAG. * + * [Since 2.14] Use value~1 if you want to access the table directory + * of the (currently selected) font. + * * offset :: * The starting offset in the table (or file if tag~==~0). * diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h index da0af5d3f23..56bb0a3ee5e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h @@ -4,7 +4,7 @@ * * Tags for TrueType and OpenType tables (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/include/ft2build.h b/src/java.desktop/share/native/libfreetype/include/ft2build.h index d3d7685039c..3008aea7cf5 100644 --- a/src/java.desktop/share/native/libfreetype/include/ft2build.h +++ b/src/java.desktop/share/native/libfreetype/include/ft2build.h @@ -4,7 +4,7 @@ * * FreeType 2 build and setup macros. * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c new file mode 100644 index 00000000000..6637cacfccf --- /dev/null +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c @@ -0,0 +1,1612 @@ +/**************************************************************************** + * + * afadjust.c + * + * Auto-fitter routines to adjust components based on charcode (body). + * + * Copyright (C) 2023-2025 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Craig White . + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#include "afadjust.h" +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ +# include "afgsub.h" +#endif + +#include +#include +#include +#include + +#define AF_ADJUSTMENT_DATABASE_LENGTH \ + ( sizeof ( adjustment_database ) / \ + sizeof ( adjustment_database[0] ) ) + +#undef FT_COMPONENT +#define FT_COMPONENT afadjust + + + typedef struct AF_AdjustmentDatabaseEntry_ + { + FT_UInt32 codepoint; + FT_UInt32 flags; + + } AF_AdjustmentDatabaseEntry; + + + /* + All entries in this list must be sorted by ascending Unicode code + points. The table entries are 3 numbers consisting of: + + - Unicode code point. + - The vertical adjustment type. This should be a combination of the + AF_ADJUST_XXX and AF_IGNORE_XXX macros. + */ + static AF_AdjustmentDatabaseEntry adjustment_database[] = + { + /* C0 Controls and Basic Latin */ + { 0x21, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ! */ + { 0x51, AF_IGNORE_CAPITAL_BOTTOM } , /* Q */ + { 0x3F, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ? */ + { 0x69, AF_ADJUST_UP }, /* i */ + { 0x6A, AF_ADJUST_UP }, /* j */ +#if 0 + /* XXX TODO */ + { 0x7E, AF_ADJUST_TILDE_TOP }, /* ~ */ +#endif + + /* C1 Controls and Latin-1 Supplement */ + { 0xA1, AF_ADJUST_UP }, /* ¡ */ + { 0xA6, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ¦ */ + { 0xAA, AF_ADJUST_UP }, /* ª */ + { 0xBA, AF_ADJUST_UP }, /* º */ + { 0xBF, AF_ADJUST_UP }, /* ¿ */ + + { 0xC0, AF_ADJUST_UP }, /* À */ + { 0xC1, AF_ADJUST_UP }, /* Á */ + { 0xC2, AF_ADJUST_UP }, /* Â */ + { 0xC3, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Ã */ + { 0xC4, AF_ADJUST_UP }, /* Ä */ + { 0xC5, AF_ADJUST_UP }, /* Å */ + { 0xC7, AF_IGNORE_CAPITAL_BOTTOM }, /* Ç */ + { 0xC8, AF_ADJUST_UP }, /* È */ + { 0xC9, AF_ADJUST_UP }, /* É */ + { 0xCA, AF_ADJUST_UP }, /* Ê */ + { 0xCB, AF_ADJUST_UP }, /* Ë */ + { 0xCC, AF_ADJUST_UP }, /* Ì */ + { 0xCD, AF_ADJUST_UP }, /* Í */ + { 0xCE, AF_ADJUST_UP }, /* Î */ + { 0xCF, AF_ADJUST_UP }, /* Ï */ + + { 0xD1, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Ñ */ + { 0xD2, AF_ADJUST_UP }, /* Ò */ + { 0xD3, AF_ADJUST_UP }, /* Ó */ + { 0xD4, AF_ADJUST_UP }, /* Ô */ + { 0xD5, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Õ */ + { 0xD6, AF_ADJUST_UP }, /* Ö */ + { 0xD8, AF_IGNORE_CAPITAL_TOP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ø */ + { 0xD9, AF_ADJUST_UP }, /* Ù */ + { 0xDA, AF_ADJUST_UP }, /* Ú */ + { 0xDB, AF_ADJUST_UP }, /* Û */ + { 0xDC, AF_ADJUST_UP }, /* Ü */ + { 0xDD, AF_ADJUST_UP }, /* Ý */ + + { 0xE0, AF_ADJUST_UP }, /* à */ + { 0xE1, AF_ADJUST_UP }, /* á */ + { 0xE2, AF_ADJUST_UP }, /* â */ + { 0xE3, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ã */ + { 0xE4, AF_ADJUST_UP }, /* ä */ + { 0xE5, AF_ADJUST_UP }, /* å */ + { 0xE7, AF_IGNORE_SMALL_BOTTOM }, /* ç */ + { 0xE8, AF_ADJUST_UP }, /* è */ + { 0xE9, AF_ADJUST_UP }, /* é */ + { 0xEA, AF_ADJUST_UP }, /* ê */ + { 0xEB, AF_ADJUST_UP }, /* ë */ + { 0xEC, AF_ADJUST_UP }, /* ì */ + { 0xED, AF_ADJUST_UP }, /* í */ + { 0xEE, AF_ADJUST_UP }, /* î */ + { 0xEF, AF_ADJUST_UP }, /* ï */ + + { 0xF1, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ñ */ + { 0xF2, AF_ADJUST_UP }, /* ò */ + { 0xF3, AF_ADJUST_UP }, /* ó */ + { 0xF4, AF_ADJUST_UP }, /* ô */ + { 0xF5, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* õ */ + { 0xF6, AF_ADJUST_UP }, /* ö */ + { 0xF8, AF_IGNORE_SMALL_TOP | AF_IGNORE_SMALL_BOTTOM }, /* ø */ + { 0xF9, AF_ADJUST_UP }, /* ù */ + { 0xFA, AF_ADJUST_UP }, /* ú */ + { 0xFB, AF_ADJUST_UP }, /* û */ + { 0xFC, AF_ADJUST_UP }, /* ü */ + { 0xFD, AF_ADJUST_UP }, /* ý */ + { 0xFF, AF_ADJUST_UP }, /* ÿ */ + + /* Latin Extended-A */ + { 0x100, AF_ADJUST_UP }, /* Ā */ + { 0x101, AF_ADJUST_UP }, /* ā */ + { 0x102, AF_ADJUST_UP }, /* Ă */ + { 0x103, AF_ADJUST_UP }, /* ă */ + { 0x104, AF_IGNORE_CAPITAL_BOTTOM }, /* Ą */ + { 0x105, AF_IGNORE_SMALL_BOTTOM }, /* ą */ + { 0x106, AF_ADJUST_UP }, /* Ć */ + { 0x107, AF_ADJUST_UP }, /* ć */ + { 0x108, AF_ADJUST_UP }, /* Ĉ */ + { 0x109, AF_ADJUST_UP }, /* ĉ */ + { 0x10A, AF_ADJUST_UP }, /* Ċ */ + { 0x10B, AF_ADJUST_UP }, /* ċ */ + { 0x10C, AF_ADJUST_UP }, /* Č */ + { 0x10D, AF_ADJUST_UP }, /* č */ + { 0x10E, AF_ADJUST_UP }, /* Ď */ + + { 0x112, AF_ADJUST_UP }, /* Ē */ + { 0x113, AF_ADJUST_UP }, /* ē */ + { 0x114, AF_ADJUST_UP }, /* Ĕ */ + { 0x115, AF_ADJUST_UP }, /* ĕ */ + { 0x116, AF_ADJUST_UP }, /* Ė */ + { 0x117, AF_ADJUST_UP }, /* ė */ + { 0x118, AF_IGNORE_CAPITAL_BOTTOM }, /* Ę */ + { 0x119, AF_IGNORE_SMALL_BOTTOM }, /* ę */ + { 0x11A, AF_ADJUST_UP }, /* Ě */ + { 0x11B, AF_ADJUST_UP }, /* ě */ + { 0x11C, AF_ADJUST_UP }, /* Ĝ */ + { 0x11D, AF_ADJUST_UP }, /* ĝ */ + { 0x11E, AF_ADJUST_UP }, /* Ğ */ + { 0x11F, AF_ADJUST_UP }, /* ğ */ + + { 0x120, AF_ADJUST_UP }, /* Ġ */ + { 0x121, AF_ADJUST_UP }, /* ġ */ + { 0x122, AF_ADJUST_DOWN }, /* Ģ */ + { 0x123, AF_ADJUST_UP }, /* ģ */ + { 0x124, AF_ADJUST_UP }, /* Ĥ */ + { 0x125, AF_ADJUST_UP }, /* ĥ */ + { 0x128, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Ĩ */ + { 0x129, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ĩ */ + { 0x12A, AF_ADJUST_UP }, /* Ī */ + { 0x12B, AF_ADJUST_UP }, /* ī */ + { 0x12C, AF_ADJUST_UP }, /* Ĭ */ + { 0x12D, AF_ADJUST_UP }, /* ĭ */ + { 0x12E, AF_IGNORE_CAPITAL_BOTTOM }, /* Į */ + { 0x12F, AF_ADJUST_UP | AF_IGNORE_SMALL_BOTTOM }, /* į */ + + { 0x130, AF_ADJUST_UP }, /* İ */ + { 0x133, AF_ADJUST_UP }, /* ij */ + { 0x134, AF_ADJUST_UP }, /* Ĵ */ + { 0x135, AF_ADJUST_UP }, /* ĵ */ + { 0x136, AF_ADJUST_DOWN }, /* Ķ */ + { 0x137, AF_ADJUST_DOWN }, /* ķ */ + { 0x139, AF_ADJUST_UP }, /* Ĺ */ + { 0x13A, AF_ADJUST_UP }, /* ĺ */ + { 0x13B, AF_ADJUST_DOWN }, /* Ļ */ + { 0x13C, AF_ADJUST_DOWN }, /* ļ */ + + { 0x143, AF_ADJUST_UP }, /* Ń */ + { 0x144, AF_ADJUST_UP }, /* ń */ + { 0x145, AF_ADJUST_DOWN }, /* Ņ */ + { 0x146, AF_ADJUST_DOWN }, /* ņ */ + { 0x147, AF_ADJUST_UP }, /* Ň */ + { 0x148, AF_ADJUST_UP }, /* ň */ + { 0x14C, AF_ADJUST_UP }, /* Ō */ + { 0x14D, AF_ADJUST_UP }, /* ō */ + { 0x14E, AF_ADJUST_UP }, /* Ŏ */ + { 0x14F, AF_ADJUST_UP }, /* ŏ */ + + { 0x150, AF_ADJUST_UP }, /* Ő */ + { 0x151, AF_ADJUST_UP }, /* ő */ + { 0x154, AF_ADJUST_UP }, /* Ŕ */ + { 0x155, AF_ADJUST_UP }, /* ŕ */ + { 0x156, AF_ADJUST_DOWN }, /* Ŗ */ + { 0x157, AF_ADJUST_DOWN }, /* ŗ */ + { 0x158, AF_ADJUST_UP }, /* Ř */ + { 0x159, AF_ADJUST_UP }, /* ř */ + { 0x15A, AF_ADJUST_UP }, /* Ś */ + { 0x15B, AF_ADJUST_UP }, /* ś */ + { 0x15C, AF_ADJUST_UP }, /* Ŝ */ + { 0x15D, AF_ADJUST_UP }, /* ŝ */ + { 0x15E, AF_IGNORE_CAPITAL_BOTTOM }, /* Ş */ + { 0x15F, AF_IGNORE_SMALL_BOTTOM }, /* ş */ + + { 0x160, AF_ADJUST_UP }, /* Š */ + { 0x161, AF_ADJUST_UP }, /* š */ + { 0x162, AF_IGNORE_CAPITAL_BOTTOM }, /* Ţ */ + { 0x163, AF_IGNORE_SMALL_BOTTOM }, /* ţ */ + { 0x164, AF_ADJUST_UP }, /* Ť */ + { 0x168, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Ũ */ + { 0x169, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ũ */ + { 0x16A, AF_ADJUST_UP }, /* Ū */ + { 0x16B, AF_ADJUST_UP }, /* ū */ + { 0x16C, AF_ADJUST_UP }, /* Ŭ */ + { 0x16D, AF_ADJUST_UP }, /* ŭ */ + { 0x16E, AF_ADJUST_UP }, /* Ů */ + { 0x16F, AF_ADJUST_UP }, /* ů */ + + { 0x170, AF_ADJUST_UP }, /* Ű */ + { 0x171, AF_ADJUST_UP }, /* ű */ + { 0x172, AF_IGNORE_CAPITAL_BOTTOM }, /* Ų */ + { 0x173, AF_IGNORE_SMALL_BOTTOM }, /* ų */ + { 0x174, AF_ADJUST_UP }, /* Ŵ */ + { 0x175, AF_ADJUST_UP }, /* ŵ */ + { 0x176, AF_ADJUST_UP }, /* Ŷ */ + { 0x177, AF_ADJUST_UP }, /* ŷ */ + { 0x178, AF_ADJUST_UP }, /* Ÿ */ + { 0x179, AF_ADJUST_UP }, /* Ź */ + { 0x17A, AF_ADJUST_UP }, /* ź */ + { 0x17B, AF_ADJUST_UP }, /* Ż */ + { 0x17C, AF_ADJUST_UP }, /* ż */ + { 0x17D, AF_ADJUST_UP }, /* Ž */ + { 0x17E, AF_ADJUST_UP }, /* ž */ + + /* Latin Extended-B */ + { 0x187, AF_IGNORE_CAPITAL_TOP }, /* Ƈ */ + { 0x188, AF_IGNORE_SMALL_TOP }, /* ƈ */ + + { 0x1A0, AF_IGNORE_CAPITAL_TOP }, /* Ơ */ + { 0x1A1, AF_IGNORE_SMALL_TOP }, /* ơ */ + { 0x1A5, AF_IGNORE_SMALL_TOP }, /* ƥ */ + { 0x1AB, AF_IGNORE_SMALL_BOTTOM }, /* ƫ */ + { 0x1AE, AF_IGNORE_CAPITAL_BOTTOM }, /* Ʈ */ + { 0x1AF, AF_IGNORE_CAPITAL_TOP }, /* Ư */ + + { 0x1B0, AF_IGNORE_SMALL_TOP }, /* ư */ + { 0x1B4, AF_IGNORE_SMALL_TOP }, /* ƴ */ + + { 0x1C3, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ǃ */ + { 0x1C4, AF_ADJUST_UP }, /* DŽ */ +#if 0 + { 0x1C5, AF_ADJUST_UP }, /* Dž */ + { 0x1C6, AF_ADJUST_UP }, /* dž */ + { 0x1C8, AF_ADJUST_UP }, /* Lj */ + { 0x1C9, AF_ADJUST_UP }, /* lj */ + { 0x1CB, AF_ADJUST_UP }, /* Nj */ +#endif + { 0x1CC, AF_ADJUST_UP }, /* nj */ + { 0x1CD, AF_ADJUST_UP }, /* Ǎ */ + { 0x1CE, AF_ADJUST_UP }, /* ǎ */ + { 0x1CF, AF_ADJUST_UP }, /* Ǐ */ + + { 0x1D0, AF_ADJUST_UP }, /* ǐ */ + { 0x1D1, AF_ADJUST_UP }, /* Ǒ */ + { 0x1D2, AF_ADJUST_UP }, /* ǒ */ + { 0x1D3, AF_ADJUST_UP }, /* Ǔ */ + { 0x1D4, AF_ADJUST_UP }, /* ǔ */ + { 0x1D5, AF_ADJUST_UP2 }, /* Ǖ */ + { 0x1D6, AF_ADJUST_UP2 }, /* ǖ */ + { 0x1D7, AF_ADJUST_UP2 }, /* Ǘ */ + { 0x1D8, AF_ADJUST_UP2 }, /* ǘ */ + { 0x1D9, AF_ADJUST_UP2 }, /* Ǚ */ + { 0x1DA, AF_ADJUST_UP2 }, /* ǚ */ + { 0x1DB, AF_ADJUST_UP2 }, /* Ǜ */ + { 0x1DC, AF_ADJUST_UP2 }, /* ǜ */ + { 0x1DE, AF_ADJUST_UP2 }, /* Ǟ */ + { 0x1DF, AF_ADJUST_UP2 }, /* ǟ */ + + { 0x1E0, AF_ADJUST_UP2 }, /* Ǡ */ + { 0x1E1, AF_ADJUST_UP2 }, /* ǡ */ + { 0x1E2, AF_ADJUST_UP }, /* Ǣ */ + { 0x1E3, AF_ADJUST_UP }, /* ǣ */ + { 0x1E6, AF_ADJUST_UP }, /* Ǧ */ + { 0x1E7, AF_ADJUST_UP }, /* ǧ */ + { 0x1E8, AF_ADJUST_UP }, /* Ǩ */ + { 0x1E9, AF_ADJUST_UP }, /* ǩ */ + { 0x1EA, AF_IGNORE_CAPITAL_BOTTOM }, /* Ǫ */ + { 0x1EB, AF_IGNORE_SMALL_BOTTOM }, /* ǫ */ + { 0x1EC, AF_ADJUST_UP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ǭ */ + { 0x1ED, AF_ADJUST_UP | AF_IGNORE_SMALL_BOTTOM }, /* ǭ */ + { 0x1EE, AF_ADJUST_UP }, /* Ǯ */ + { 0x1EF, AF_ADJUST_UP }, /* ǯ */ + + { 0x1F0, AF_ADJUST_UP }, /* ǰ */ + { 0x1F4, AF_ADJUST_UP }, /* Ǵ */ + { 0x1F5, AF_ADJUST_UP }, /* ǵ */ + { 0x1F8, AF_ADJUST_UP }, /* Ǹ */ + { 0x1F9, AF_ADJUST_UP }, /* ǹ */ + { 0x1FA, AF_ADJUST_UP2 }, /* Ǻ */ + { 0x1FB, AF_ADJUST_UP2 }, /* ǻ */ + { 0x1FC, AF_ADJUST_UP }, /* Ǽ */ + { 0x1FD, AF_ADJUST_UP }, /* ǽ */ + { 0x1FE, AF_ADJUST_UP }, /* Ǿ */ + { 0x1FF, AF_ADJUST_UP }, /* ǿ */ + + { 0x200, AF_ADJUST_UP }, /* Ȁ */ + { 0x201, AF_ADJUST_UP }, /* ȁ */ + { 0x202, AF_ADJUST_UP }, /* Ȃ */ + { 0x203, AF_ADJUST_UP }, /* ȃ */ + { 0x204, AF_ADJUST_UP }, /* Ȅ */ + { 0x205, AF_ADJUST_UP }, /* ȅ */ + { 0x206, AF_ADJUST_UP }, /* Ȇ */ + { 0x207, AF_ADJUST_UP }, /* ȇ */ + { 0x208, AF_ADJUST_UP }, /* Ȉ */ + { 0x209, AF_ADJUST_UP }, /* ȉ */ + { 0x20A, AF_ADJUST_UP }, /* Ȋ */ + { 0x20B, AF_ADJUST_UP }, /* ȋ */ + { 0x20C, AF_ADJUST_UP }, /* Ȍ */ + { 0x20D, AF_ADJUST_UP }, /* ȍ */ + { 0x20E, AF_ADJUST_UP }, /* Ȏ */ + { 0x20F, AF_ADJUST_UP }, /* ȏ */ + + { 0x210, AF_ADJUST_UP }, /* Ȑ */ + { 0x211, AF_ADJUST_UP }, /* ȑ */ + { 0x212, AF_ADJUST_UP }, /* Ȓ */ + { 0x213, AF_ADJUST_UP }, /* ȓ */ + { 0x214, AF_ADJUST_UP }, /* Ȕ */ + { 0x215, AF_ADJUST_UP }, /* ȕ */ + { 0x216, AF_ADJUST_UP }, /* Ȗ */ + { 0x217, AF_ADJUST_UP }, /* ȗ */ + { 0x218, AF_ADJUST_DOWN }, /* Ș */ + { 0x219, AF_ADJUST_DOWN }, /* ș */ + { 0x21A, AF_ADJUST_DOWN }, /* Ț */ + { 0x21B, AF_ADJUST_DOWN }, /* ț */ + { 0x21E, AF_ADJUST_UP }, /* Ȟ */ + { 0x21F, AF_ADJUST_UP }, /* ȟ */ + + { 0x224, AF_IGNORE_CAPITAL_BOTTOM }, /* Ȥ */ + { 0x225, AF_IGNORE_SMALL_BOTTOM }, /* ȥ */ + { 0x226, AF_ADJUST_UP }, /* Ȧ */ + { 0x227, AF_ADJUST_UP }, /* ȧ */ + { 0x228, AF_IGNORE_CAPITAL_BOTTOM }, /* Ȩ */ + { 0x229, AF_IGNORE_SMALL_BOTTOM }, /* ȩ */ + { 0x22A, AF_ADJUST_UP2 }, /* Ȫ */ + { 0x22B, AF_ADJUST_UP2 }, /* ȫ */ + { 0x22C, AF_ADJUST_UP2 }, /* Ȭ */ + { 0x22D, AF_ADJUST_UP2 }, /* ȭ */ + { 0x22E, AF_ADJUST_UP }, /* Ȯ */ + { 0x22F, AF_ADJUST_UP }, /* ȯ */ + + { 0x230, AF_ADJUST_UP2 }, /* Ȱ */ + { 0x231, AF_ADJUST_UP2 }, /* ȱ */ + { 0x232, AF_ADJUST_UP }, /* Ȳ */ + { 0x233, AF_ADJUST_UP }, /* ȳ */ + { 0x23A, AF_IGNORE_CAPITAL_TOP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ⱥ */ + { 0x23B, AF_IGNORE_CAPITAL_TOP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ȼ */ + { 0x23F, AF_IGNORE_SMALL_BOTTOM }, /* ȿ */ + + { 0x240, AF_IGNORE_SMALL_BOTTOM }, /* ɀ */ + { 0x249, AF_ADJUST_UP }, /* ɉ */ + + /* IPA Extensions */ + { 0x256, AF_IGNORE_SMALL_BOTTOM }, /* ɖ */ + + { 0x260, AF_IGNORE_SMALL_TOP }, /* ɠ */ + { 0x267, AF_IGNORE_SMALL_BOTTOM }, /* ɧ */ + { 0x268, AF_ADJUST_UP }, /* ɨ */ + + { 0x272, AF_IGNORE_SMALL_BOTTOM }, /* ɲ */ + { 0x273, AF_IGNORE_SMALL_BOTTOM }, /* ɳ */ + { 0x27B, AF_IGNORE_SMALL_BOTTOM }, /* ɻ */ + { 0x27D, AF_IGNORE_SMALL_BOTTOM }, /* ɽ */ + + { 0x282, AF_IGNORE_SMALL_BOTTOM }, /* ʂ */ + { 0x288, AF_IGNORE_SMALL_BOTTOM }, /* ʈ */ + + { 0x290, AF_IGNORE_SMALL_BOTTOM }, /* ʐ */ + { 0x29B, AF_IGNORE_SMALL_TOP }, /* ʛ */ + + { 0x2A0, AF_IGNORE_SMALL_TOP }, /* ʠ */ + + /* Spacing Modifier Letters */ + { 0x2B2, AF_ADJUST_UP }, /* ʲ */ + { 0x2B5, AF_IGNORE_SMALL_BOTTOM }, /* ʵ */ + + /* Greek and Coptic */ + { 0x390, AF_ADJUST_UP2 }, /* ΐ */ + + { 0x3AA, AF_ADJUST_UP }, /* Ϊ */ + { 0x3AB, AF_ADJUST_UP }, /* Ϋ */ + { 0x3AC, AF_ADJUST_UP }, /* ά */ + { 0x3AD, AF_ADJUST_UP }, /* έ */ + { 0x3AE, AF_ADJUST_UP }, /* ή */ + { 0x3AF, AF_ADJUST_UP }, /* ί */ + + { 0x3B0, AF_ADJUST_UP2 }, /* ΰ */ + + { 0x3CA, AF_ADJUST_UP }, /* ϊ */ + { 0x3CB, AF_ADJUST_UP }, /* ϋ */ + { 0x3CC, AF_ADJUST_UP }, /* ό */ + { 0x3CD, AF_ADJUST_UP }, /* ύ */ + { 0x3CE, AF_ADJUST_UP }, /* ώ */ + { 0x3CF, AF_IGNORE_CAPITAL_BOTTOM }, /* Ϗ */ + + { 0x3D4, AF_ADJUST_UP }, /* ϔ */ + { 0x3D7, AF_IGNORE_SMALL_BOTTOM }, /* ϗ */ + { 0x3D9, AF_IGNORE_SMALL_BOTTOM }, /* ϙ */ + + { 0x3E2, AF_IGNORE_CAPITAL_BOTTOM }, /* Ϣ */ + { 0x3E3, AF_IGNORE_SMALL_BOTTOM }, /* ϣ */ + + { 0x3F3, AF_ADJUST_UP }, /* ϳ */ + + /* Cyrillic */ + { 0x400, AF_ADJUST_UP }, /* Ѐ */ + { 0x401, AF_ADJUST_UP }, /* Ё */ + { 0x403, AF_ADJUST_UP }, /* Ѓ */ + { 0x407, AF_ADJUST_UP }, /* Ї */ + { 0x40C, AF_ADJUST_UP }, /* Ќ */ + { 0x40D, AF_ADJUST_UP }, /* Ѝ */ + { 0x40E, AF_ADJUST_UP }, /* Ў */ + { 0x40F, AF_IGNORE_CAPITAL_BOTTOM }, /* Џ */ + + { 0x419, AF_ADJUST_UP }, /* Й */ + + { 0x426, AF_IGNORE_CAPITAL_BOTTOM }, /* Ц */ + { 0x429, AF_IGNORE_CAPITAL_BOTTOM }, /* Щ */ + + { 0x439, AF_ADJUST_UP }, /* й */ + + { 0x446, AF_IGNORE_SMALL_BOTTOM }, /* ц */ + { 0x449, AF_IGNORE_SMALL_BOTTOM }, /* щ */ + + { 0x450, AF_ADJUST_UP }, /* ѐ */ + { 0x451, AF_ADJUST_UP }, /* ё */ + { 0x453, AF_ADJUST_UP }, /* ѓ */ + { 0x456, AF_ADJUST_UP }, /* і */ + { 0x457, AF_ADJUST_UP }, /* ї */ + { 0x458, AF_ADJUST_UP }, /* ј */ + { 0x45C, AF_ADJUST_UP }, /* ќ */ + { 0x45D, AF_ADJUST_UP }, /* ѝ */ + { 0x45E, AF_ADJUST_UP }, /* ў */ + { 0x45F, AF_IGNORE_SMALL_BOTTOM }, /* џ */ + + { 0x476, AF_ADJUST_UP }, /* Ѷ */ + { 0x477, AF_ADJUST_UP }, /* ѷ */ + { 0x47C, AF_ADJUST_UP2 }, /* Ѽ */ + { 0x47D, AF_ADJUST_UP2 }, /* ѽ */ + { 0x47E, AF_ADJUST_UP }, /* Ѿ */ + { 0x47F, AF_ADJUST_UP }, /* ѿ */ + + { 0x480, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҁ */ + { 0x481, AF_IGNORE_SMALL_BOTTOM }, /* ҁ */ + { 0x48A, AF_ADJUST_UP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ҋ */ + { 0x48B, AF_ADJUST_UP | AF_IGNORE_SMALL_BOTTOM }, /* ҋ */ + + { 0x490, AF_IGNORE_CAPITAL_TOP }, /* Ґ */ + { 0x491, AF_IGNORE_SMALL_TOP }, /* ґ */ + { 0x496, AF_IGNORE_CAPITAL_BOTTOM }, /* Җ */ + { 0x497, AF_IGNORE_SMALL_BOTTOM }, /* җ */ + { 0x498, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҙ */ + { 0x499, AF_IGNORE_SMALL_BOTTOM }, /* ҙ */ + { 0x49A, AF_IGNORE_CAPITAL_BOTTOM }, /* Қ */ + { 0x49B, AF_IGNORE_SMALL_BOTTOM }, /* қ */ + + { 0x4A2, AF_IGNORE_CAPITAL_BOTTOM }, /* Ң */ + { 0x4A3, AF_IGNORE_SMALL_BOTTOM }, /* ң */ + { 0x4AA, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҫ */ + { 0x4AB, AF_IGNORE_SMALL_BOTTOM }, /* ҫ */ + { 0x4AC, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҭ */ + { 0x4AD, AF_IGNORE_SMALL_BOTTOM }, /* ҭ */ + + { 0x4B2, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҳ */ + { 0x4B3, AF_IGNORE_SMALL_BOTTOM }, /* ҳ */ + { 0x4B4, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҵ */ + { 0x4B5, AF_IGNORE_SMALL_BOTTOM }, /* ҵ */ + { 0x4B6, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҷ */ + { 0x4B7, AF_IGNORE_SMALL_BOTTOM }, /* ҷ */ + { 0x4BE, AF_IGNORE_CAPITAL_BOTTOM }, /* Ҿ */ + { 0x4BF, AF_IGNORE_SMALL_BOTTOM }, /* ҿ */ + + { 0x4C1, AF_ADJUST_UP }, /* Ӂ */ + { 0x4C2, AF_ADJUST_UP }, /* ӂ */ + { 0x4C5, AF_IGNORE_CAPITAL_BOTTOM }, /* Ӆ */ + { 0x4C6, AF_IGNORE_SMALL_BOTTOM }, /* ӆ */ + { 0x4C9, AF_IGNORE_CAPITAL_BOTTOM }, /* Ӊ */ + { 0x4CA, AF_IGNORE_SMALL_BOTTOM }, /* ӊ */ + { 0x4CB, AF_IGNORE_CAPITAL_BOTTOM }, /* Ӌ */ + { 0x4CC, AF_IGNORE_SMALL_BOTTOM }, /* ӌ */ + { 0x4CD, AF_IGNORE_CAPITAL_BOTTOM }, /* Ӎ */ + { 0x4CE, AF_IGNORE_SMALL_BOTTOM }, /* ӎ */ + + { 0x4D0, AF_ADJUST_UP }, /* Ӑ */ + { 0x4D1, AF_ADJUST_UP }, /* ӑ */ + { 0x4D2, AF_ADJUST_UP }, /* Ӓ */ + { 0x4D3, AF_ADJUST_UP }, /* ӓ */ + { 0x4D6, AF_ADJUST_UP }, /* Ӗ */ + { 0x4D7, AF_ADJUST_UP }, /* ӗ */ + { 0x4DA, AF_ADJUST_UP }, /* Ӛ */ + { 0x4DB, AF_ADJUST_UP }, /* ӛ */ + { 0x4DC, AF_ADJUST_UP }, /* Ӝ */ + { 0x4DD, AF_ADJUST_UP }, /* ӝ */ + { 0x4DE, AF_ADJUST_UP }, /* Ӟ */ + { 0x4DF, AF_ADJUST_UP }, /* ӟ */ + + { 0x4E2, AF_ADJUST_UP }, /* Ӣ */ + { 0x4E3, AF_ADJUST_UP }, /* ӣ */ + { 0x4E4, AF_ADJUST_UP }, /* Ӥ */ + { 0x4E5, AF_ADJUST_UP }, /* ӥ */ + { 0x4E6, AF_ADJUST_UP }, /* Ӧ */ + { 0x4E7, AF_ADJUST_UP }, /* ӧ */ + { 0x4EA, AF_ADJUST_UP }, /* Ӫ */ + { 0x4EB, AF_ADJUST_UP }, /* ӫ */ + { 0x4EC, AF_ADJUST_UP }, /* Ӭ */ + { 0x4ED, AF_ADJUST_UP }, /* ӭ */ + { 0x4EE, AF_ADJUST_UP }, /* Ӯ */ + { 0x4EF, AF_ADJUST_UP }, /* ӯ */ + + { 0x4F0, AF_ADJUST_UP }, /* Ӱ */ + { 0x4F1, AF_ADJUST_UP }, /* ӱ */ + { 0x4F2, AF_ADJUST_UP }, /* Ӳ */ + { 0x4F3, AF_ADJUST_UP }, /* ӳ */ + { 0x4F4, AF_ADJUST_UP }, /* Ӵ */ + { 0x4F5, AF_ADJUST_UP }, /* ӵ */ + { 0x4F6, AF_IGNORE_CAPITAL_BOTTOM }, /* Ӷ */ + { 0x4F7, AF_IGNORE_SMALL_BOTTOM }, /* ӷ */ + { 0x4F8, AF_ADJUST_UP }, /* Ӹ */ + { 0x4F9, AF_ADJUST_UP }, /* ӹ */ + { 0x4FA, AF_IGNORE_CAPITAL_BOTTOM }, /* Ӻ */ + { 0x4FB, AF_IGNORE_SMALL_BOTTOM }, /* ӻ */ + + /* Cyrillic Supplement */ + { 0x506, AF_IGNORE_CAPITAL_BOTTOM }, /* Ԇ */ + { 0x507, AF_IGNORE_SMALL_BOTTOM }, /* ԇ */ + + { 0x524, AF_IGNORE_CAPITAL_BOTTOM }, /* Ԥ */ + { 0x525, AF_IGNORE_SMALL_BOTTOM }, /* ԥ */ + { 0x526, AF_IGNORE_CAPITAL_BOTTOM }, /* Ԧ */ + { 0x527, AF_IGNORE_SMALL_BOTTOM }, /* ԧ */ + { 0x52E, AF_IGNORE_CAPITAL_BOTTOM }, /* Ԯ */ + { 0x52F, AF_IGNORE_SMALL_BOTTOM }, /* ԯ */ + + /* Cherokee */ + { 0x13A5, AF_ADJUST_UP }, /* Ꭵ */ + + /* Phonetic Extensions */ + { 0x1D09, AF_ADJUST_DOWN }, /* ᴉ */ + + { 0x1D4E, AF_ADJUST_DOWN }, /* ᵎ */ + + { 0x1D51, AF_IGNORE_SMALL_BOTTOM }, /* ᵑ */ + + { 0x1D62, AF_ADJUST_UP }, /* ᵢ */ + + /* Phonetic Extensions Supplement */ + { 0x1D80, AF_IGNORE_SMALL_BOTTOM }, /* ᶀ */ + { 0x1D81, AF_IGNORE_SMALL_BOTTOM }, /* ᶁ */ + { 0x1D82, AF_IGNORE_SMALL_BOTTOM }, /* ᶂ */ + { 0x1D84, AF_IGNORE_SMALL_BOTTOM }, /* ᶄ */ + { 0x1D85, AF_IGNORE_SMALL_BOTTOM }, /* ᶅ */ + { 0x1D86, AF_IGNORE_SMALL_BOTTOM }, /* ᶆ */ + { 0x1D87, AF_IGNORE_SMALL_BOTTOM }, /* ᶇ */ + { 0x1D89, AF_IGNORE_SMALL_BOTTOM }, /* ᶉ */ + { 0x1D8A, AF_IGNORE_SMALL_BOTTOM }, /* ᶊ */ + { 0x1D8C, AF_IGNORE_SMALL_BOTTOM }, /* ᶌ */ + { 0x1D8D, AF_IGNORE_SMALL_BOTTOM }, /* ᶍ */ + { 0x1D8E, AF_IGNORE_SMALL_BOTTOM }, /* ᶎ */ + { 0x1D8F, AF_IGNORE_SMALL_BOTTOM }, /* ᶏ */ + + { 0x1D90, AF_IGNORE_SMALL_BOTTOM }, /* ᶐ */ + { 0x1D91, AF_IGNORE_SMALL_BOTTOM }, /* ᶑ */ + { 0x1D92, AF_IGNORE_SMALL_BOTTOM }, /* ᶒ */ + { 0x1D93, AF_IGNORE_SMALL_BOTTOM }, /* ᶓ */ + { 0x1D94, AF_IGNORE_SMALL_BOTTOM }, /* ᶔ */ + { 0x1D95, AF_IGNORE_SMALL_BOTTOM }, /* ᶕ */ + { 0x1D96, AF_ADJUST_UP | AF_IGNORE_SMALL_BOTTOM }, /* ᶖ */ + { 0x1D97, AF_IGNORE_SMALL_BOTTOM }, /* ᶗ */ + { 0x1D98, AF_IGNORE_SMALL_BOTTOM }, /* ᶘ */ + { 0x1D99, AF_IGNORE_SMALL_BOTTOM }, /* ᶙ */ + { 0x1D9A, AF_IGNORE_SMALL_BOTTOM }, /* ᶚ */ + + { 0x1DA4, AF_ADJUST_UP }, /* ᶤ */ + { 0x1DA8, AF_ADJUST_UP }, /* ᶨ */ + { 0x1DA9, AF_IGNORE_SMALL_BOTTOM }, /* ᶩ */ + { 0x1DAA, AF_IGNORE_SMALL_BOTTOM }, /* ᶪ */ + { 0x1DAC, AF_IGNORE_SMALL_BOTTOM }, /* ᶬ */ + { 0x1DAE, AF_IGNORE_SMALL_BOTTOM }, /* ᶮ */ + { 0x1DAF, AF_IGNORE_SMALL_BOTTOM }, /* ᶯ */ + + { 0x1DB3, AF_IGNORE_SMALL_BOTTOM }, /* ᶳ */ + { 0x1DB5, AF_IGNORE_SMALL_BOTTOM }, /* ᶵ */ + { 0x1DBC, AF_IGNORE_SMALL_BOTTOM }, /* ᶼ */ + + /* Latin Extended Additional */ + { 0x1E00, AF_ADJUST_DOWN }, /* Ḁ */ + { 0x1E01, AF_ADJUST_DOWN }, /* ḁ */ + { 0x1E02, AF_ADJUST_UP }, /* Ḃ */ + { 0x1E03, AF_ADJUST_UP }, /* ḃ */ + { 0x1E04, AF_ADJUST_DOWN }, /* Ḅ */ + { 0x1E05, AF_ADJUST_DOWN }, /* ḅ */ + { 0x1E06, AF_ADJUST_DOWN }, /* Ḇ */ + { 0x1E07, AF_ADJUST_DOWN }, /* ḇ */ + { 0x1E08, AF_ADJUST_UP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ḉ */ + { 0x1E09, AF_ADJUST_UP | AF_IGNORE_SMALL_BOTTOM }, /* ḉ */ + { 0x1E0A, AF_ADJUST_UP }, /* Ḋ */ + { 0x1E0B, AF_ADJUST_UP }, /* ḋ */ + { 0x1E0C, AF_ADJUST_DOWN }, /* Ḍ */ + { 0x1E0D, AF_ADJUST_DOWN }, /* ḍ */ + { 0x1E0E, AF_ADJUST_DOWN }, /* Ḏ */ + { 0x1E0F, AF_ADJUST_DOWN }, /* ḏ */ + + { 0x1E10, AF_ADJUST_DOWN }, /* Ḑ */ + { 0x1E11, AF_ADJUST_DOWN }, /* ḑ */ + { 0x1E12, AF_ADJUST_DOWN }, /* Ḓ */ + { 0x1E13, AF_ADJUST_DOWN }, /* ḓ */ + { 0x1E14, AF_ADJUST_UP2 }, /* Ḕ */ + { 0x1E15, AF_ADJUST_UP2 }, /* ḕ */ + { 0x1E16, AF_ADJUST_UP2 }, /* Ḗ */ + { 0x1E17, AF_ADJUST_UP2 }, /* ḗ */ + { 0x1E18, AF_ADJUST_DOWN }, /* Ḙ */ + { 0x1E19, AF_ADJUST_DOWN }, /* ḙ */ + { 0x1E1A, AF_ADJUST_DOWN | AF_ADJUST_TILDE_BOTTOM }, /* Ḛ */ + { 0x1E1B, AF_ADJUST_DOWN | AF_ADJUST_TILDE_BOTTOM }, /* ḛ */ + { 0x1E1C, AF_ADJUST_UP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ḝ */ + { 0x1E1D, AF_ADJUST_UP | AF_IGNORE_SMALL_BOTTOM }, /* ḝ */ + { 0x1E1E, AF_ADJUST_UP }, /* Ḟ */ + { 0x1E1F, AF_ADJUST_UP }, /* ḟ */ + + { 0x1E20, AF_ADJUST_UP }, /* Ḡ */ + { 0x1E21, AF_ADJUST_UP }, /* ḡ */ + { 0x1E22, AF_ADJUST_UP }, /* Ḣ */ + { 0x1E23, AF_ADJUST_UP }, /* ḣ */ + { 0x1E24, AF_ADJUST_DOWN }, /* Ḥ */ + { 0x1E25, AF_ADJUST_DOWN }, /* ḥ */ + { 0x1E26, AF_ADJUST_UP }, /* Ḧ */ + { 0x1E27, AF_ADJUST_UP }, /* ḧ */ + { 0x1E28, AF_IGNORE_CAPITAL_BOTTOM }, /* Ḩ */ + { 0x1E29, AF_IGNORE_SMALL_BOTTOM }, /* ḩ */ + { 0x1E2A, AF_ADJUST_DOWN }, /* Ḫ */ + { 0x1E2B, AF_ADJUST_DOWN }, /* ḫ */ + { 0x1E2C, AF_ADJUST_DOWN | AF_ADJUST_TILDE_BOTTOM }, /* Ḭ */ + { 0x1E2D, AF_ADJUST_UP | AF_ADJUST_DOWN | AF_ADJUST_TILDE_BOTTOM }, /* ḭ */ + { 0x1E2E, AF_ADJUST_UP2 }, /* Ḯ */ + { 0x1E2F, AF_ADJUST_UP2 }, /* ḯ */ + + { 0x1E30, AF_ADJUST_UP }, /* Ḱ */ + { 0x1E31, AF_ADJUST_UP }, /* ḱ */ + { 0x1E32, AF_ADJUST_DOWN }, /* Ḳ */ + { 0x1E33, AF_ADJUST_DOWN }, /* ḳ */ + { 0x1E34, AF_ADJUST_DOWN }, /* Ḵ */ + { 0x1E35, AF_ADJUST_DOWN }, /* ḵ */ + { 0x1E36, AF_ADJUST_DOWN }, /* Ḷ */ + { 0x1E37, AF_ADJUST_DOWN }, /* ḷ */ + { 0x1E38, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* Ḹ */ + { 0x1E39, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ḹ */ + { 0x1E3A, AF_ADJUST_DOWN }, /* Ḻ */ + { 0x1E3B, AF_ADJUST_DOWN }, /* ḻ */ + { 0x1E3C, AF_ADJUST_DOWN }, /* Ḽ */ + { 0x1E3D, AF_ADJUST_DOWN }, /* ḽ */ + { 0x1E3E, AF_ADJUST_UP }, /* Ḿ */ + { 0x1E3F, AF_ADJUST_UP }, /* ḿ */ + + { 0x1E40, AF_ADJUST_UP }, /* Ṁ */ + { 0x1E41, AF_ADJUST_UP }, /* ṁ */ + { 0x1E42, AF_ADJUST_DOWN }, /* Ṃ */ + { 0x1E43, AF_ADJUST_DOWN }, /* ṃ */ + { 0x1E44, AF_ADJUST_UP }, /* Ṅ */ + { 0x1E45, AF_ADJUST_UP }, /* ṅ */ + { 0x1E46, AF_ADJUST_DOWN }, /* Ṇ */ + { 0x1E47, AF_ADJUST_DOWN }, /* ṇ */ + { 0x1E48, AF_ADJUST_DOWN }, /* Ṉ */ + { 0x1E49, AF_ADJUST_DOWN }, /* ṉ */ + { 0x1E4A, AF_ADJUST_DOWN }, /* Ṋ */ + { 0x1E4B, AF_ADJUST_DOWN }, /* ṋ */ + { 0x1E4C, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP2 }, /* Ṍ */ + { 0x1E4D, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP2 }, /* ṍ */ + { 0x1E4E, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP2 }, /* Ṏ */ + { 0x1E4F, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP2 }, /* ṏ */ + + { 0x1E50, AF_ADJUST_UP2 }, /* Ṑ */ + { 0x1E51, AF_ADJUST_UP2 }, /* ṑ */ + { 0x1E52, AF_ADJUST_UP2 }, /* Ṓ */ + { 0x1E53, AF_ADJUST_UP2 }, /* ṓ */ + { 0x1E54, AF_ADJUST_UP }, /* Ṕ */ + { 0x1E55, AF_ADJUST_UP }, /* ṕ */ + { 0x1E56, AF_ADJUST_UP }, /* Ṗ */ + { 0x1E57, AF_ADJUST_UP }, /* ṗ */ + { 0x1E58, AF_ADJUST_UP }, /* Ṙ */ + { 0x1E59, AF_ADJUST_UP }, /* ṙ */ + { 0x1E5A, AF_ADJUST_DOWN }, /* Ṛ */ + { 0x1E5B, AF_ADJUST_DOWN }, /* ṛ */ + { 0x1E5C, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* Ṝ */ + { 0x1E5D, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ṝ */ + { 0x1E5E, AF_ADJUST_DOWN }, /* Ṟ */ + { 0x1E5F, AF_ADJUST_DOWN }, /* ṟ */ + + { 0x1E60, AF_ADJUST_UP }, /* Ṡ */ + { 0x1E61, AF_ADJUST_UP }, /* ṡ */ + { 0x1E62, AF_ADJUST_DOWN }, /* Ṣ */ + { 0x1E63, AF_ADJUST_DOWN }, /* ṣ */ + { 0x1E64, AF_ADJUST_UP }, /* Ṥ */ + { 0x1E65, AF_ADJUST_UP }, /* ṥ */ + { 0x1E66, AF_ADJUST_UP }, /* Ṧ */ + { 0x1E67, AF_ADJUST_UP }, /* ṧ */ + { 0x1E68, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* Ṩ */ + { 0x1E69, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ṩ */ + { 0x1E6A, AF_ADJUST_UP }, /* Ṫ */ + { 0x1E6B, AF_ADJUST_UP }, /* ṫ */ + { 0x1E6C, AF_ADJUST_DOWN }, /* Ṭ */ + { 0x1E6D, AF_ADJUST_DOWN }, /* ṭ */ + { 0x1E6E, AF_ADJUST_DOWN }, /* Ṯ */ + { 0x1E6F, AF_ADJUST_DOWN }, /* ṯ */ + + { 0x1E70, AF_ADJUST_DOWN }, /* Ṱ */ + { 0x1E71, AF_ADJUST_DOWN }, /* ṱ */ + { 0x1E72, AF_ADJUST_DOWN }, /* Ṳ */ + { 0x1E73, AF_ADJUST_DOWN }, /* ṳ */ + { 0x1E74, AF_ADJUST_DOWN | AF_ADJUST_TILDE_BOTTOM }, /* Ṵ */ + { 0x1E75, AF_ADJUST_DOWN | AF_ADJUST_TILDE_BOTTOM }, /* ṵ */ + { 0x1E76, AF_ADJUST_DOWN }, /* Ṷ */ + { 0x1E77, AF_ADJUST_DOWN }, /* ṷ */ + { 0x1E78, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP2 }, /* Ṹ */ + { 0x1E79, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP2 }, /* ṹ */ + { 0x1E7A, AF_ADJUST_UP2 }, /* Ṻ */ + { 0x1E7B, AF_ADJUST_UP2 }, /* ṻ */ + { 0x1E7C, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Ṽ */ + { 0x1E7D, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ṽ */ + { 0x1E7E, AF_ADJUST_DOWN }, /* Ṿ */ + { 0x1E7F, AF_ADJUST_DOWN }, /* ṿ */ + + { 0x1E80, AF_ADJUST_UP }, /* Ẁ */ + { 0x1E81, AF_ADJUST_UP }, /* ẁ */ + { 0x1E82, AF_ADJUST_UP }, /* Ẃ */ + { 0x1E83, AF_ADJUST_UP }, /* ẃ */ + { 0x1E84, AF_ADJUST_UP }, /* Ẅ */ + { 0x1E85, AF_ADJUST_UP }, /* ẅ */ + { 0x1E86, AF_ADJUST_UP }, /* Ẇ */ + { 0x1E87, AF_ADJUST_UP }, /* ẇ */ + { 0x1E88, AF_ADJUST_DOWN }, /* Ẉ */ + { 0x1E89, AF_ADJUST_DOWN }, /* ẉ */ + { 0x1E8A, AF_ADJUST_UP }, /* Ẋ */ + { 0x1E8B, AF_ADJUST_UP }, /* ẋ */ + { 0x1E8C, AF_ADJUST_UP }, /* Ẍ */ + { 0x1E8D, AF_ADJUST_UP }, /* ẍ */ + { 0x1E8E, AF_ADJUST_UP }, /* Ẏ */ + { 0x1E8F, AF_ADJUST_UP }, /* ẏ */ + + { 0x1E90, AF_ADJUST_UP }, /* Ẑ */ + { 0x1E91, AF_ADJUST_UP }, /* ẑ */ + { 0x1E92, AF_ADJUST_DOWN }, /* Ẓ */ + { 0x1E93, AF_ADJUST_DOWN }, /* ẓ */ + { 0x1E94, AF_ADJUST_DOWN }, /* Ẕ */ + { 0x1E95, AF_ADJUST_DOWN }, /* ẕ */ + { 0x1E96, AF_ADJUST_DOWN }, /* ẖ */ + { 0x1E97, AF_ADJUST_UP }, /* ẗ */ + { 0x1E98, AF_ADJUST_UP }, /* ẘ */ + { 0x1E99, AF_ADJUST_UP }, /* ẙ */ + { 0x1E9A, AF_ADJUST_UP }, /* ẚ */ + { 0x1E9B, AF_ADJUST_UP }, /* ẛ */ + + { 0x1EA0, AF_ADJUST_DOWN }, /* Ạ */ + { 0x1EA1, AF_ADJUST_DOWN }, /* ạ */ + { 0x1EA2, AF_ADJUST_UP }, /* Ả */ + { 0x1EA3, AF_ADJUST_UP }, /* ả */ + { 0x1EA4, AF_ADJUST_UP2 }, /* Ấ */ + { 0x1EA5, AF_ADJUST_UP2 }, /* ấ */ + { 0x1EA6, AF_ADJUST_UP2 }, /* Ầ */ + { 0x1EA7, AF_ADJUST_UP2 }, /* ầ */ + { 0x1EA8, AF_ADJUST_UP2 }, /* Ẩ */ + { 0x1EA9, AF_ADJUST_UP2 }, /* ẩ */ + { 0x1EAA, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* Ẫ */ + { 0x1EAB, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ẫ */ + { 0x1EAC, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* Ậ */ + { 0x1EAD, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ậ */ + { 0x1EAE, AF_ADJUST_UP2 }, /* Ắ */ + { 0x1EAF, AF_ADJUST_UP2 }, /* ắ */ + + { 0x1EB0, AF_ADJUST_UP2 }, /* Ằ */ + { 0x1EB1, AF_ADJUST_UP2 }, /* ằ */ + { 0x1EB2, AF_ADJUST_UP2 }, /* Ẳ */ + { 0x1EB3, AF_ADJUST_UP2 }, /* ẳ */ + { 0x1EB4, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* Ẵ */ + { 0x1EB5, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ẵ */ + { 0x1EB6, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* Ặ */ + { 0x1EB7, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ặ */ + { 0x1EB8, AF_ADJUST_DOWN }, /* Ẹ */ + { 0x1EB9, AF_ADJUST_DOWN }, /* ẹ */ + { 0x1EBA, AF_ADJUST_UP }, /* Ẻ */ + { 0x1EBB, AF_ADJUST_UP }, /* ẻ */ + { 0x1EBC, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Ẽ */ + { 0x1EBD, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ẽ */ + { 0x1EBE, AF_ADJUST_UP2 }, /* Ế */ + { 0x1EBF, AF_ADJUST_UP2 }, /* ế */ + + { 0x1EC0, AF_ADJUST_UP2 }, /* Ề */ + { 0x1EC1, AF_ADJUST_UP2 }, /* ề */ + { 0x1EC2, AF_ADJUST_UP2 }, /* Ể */ + { 0x1EC3, AF_ADJUST_UP2 }, /* ể */ + { 0x1EC4, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* Ễ */ + { 0x1EC5, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ễ */ + { 0x1EC6, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* Ệ */ + { 0x1EC7, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ệ */ + { 0x1EC8, AF_ADJUST_UP }, /* Ỉ */ + { 0x1EC9, AF_ADJUST_UP }, /* ỉ */ + { 0x1ECA, AF_ADJUST_DOWN }, /* Ị */ + { 0x1ECB, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ị */ + { 0x1ECC, AF_ADJUST_DOWN }, /* Ọ */ + { 0x1ECD, AF_ADJUST_DOWN }, /* ọ */ + { 0x1ECE, AF_ADJUST_UP }, /* Ỏ */ + { 0x1ECF, AF_ADJUST_UP }, /* ỏ */ + + { 0x1ED0, AF_ADJUST_UP2 }, /* Ố */ + { 0x1ED1, AF_ADJUST_UP2 }, /* ố */ + { 0x1ED2, AF_ADJUST_UP2 }, /* Ồ */ + { 0x1ED3, AF_ADJUST_UP2 }, /* ồ */ + { 0x1ED4, AF_ADJUST_UP2 }, /* Ổ */ + { 0x1ED5, AF_ADJUST_UP2 }, /* ổ */ + { 0x1ED6, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* Ỗ */ + { 0x1ED7, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ỗ */ + { 0x1ED8, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* Ộ */ + { 0x1ED9, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ộ */ + { 0x1EDA, AF_ADJUST_UP | AF_IGNORE_CAPITAL_TOP }, /* Ớ */ + { 0x1EDB, AF_ADJUST_UP | AF_IGNORE_SMALL_TOP }, /* ớ */ + { 0x1EDC, AF_ADJUST_UP | AF_IGNORE_CAPITAL_TOP }, /* Ờ */ + { 0x1EDD, AF_ADJUST_UP | AF_IGNORE_SMALL_TOP }, /* ờ */ + { 0x1EDE, AF_ADJUST_UP | AF_IGNORE_CAPITAL_TOP }, /* Ở */ + { 0x1EDF, AF_ADJUST_UP | AF_IGNORE_SMALL_TOP }, /* ở */ + + { 0x1EE0, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP | AF_IGNORE_CAPITAL_TOP }, /* Ỡ */ + { 0x1EE1, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP | AF_IGNORE_SMALL_TOP }, /* ỡ */ + { 0x1EE2, AF_ADJUST_DOWN | AF_IGNORE_CAPITAL_TOP }, /* Ợ */ + { 0x1EE3, AF_ADJUST_DOWN | AF_IGNORE_SMALL_TOP }, /* ợ */ + { 0x1EE4, AF_ADJUST_DOWN }, /* Ụ */ + { 0x1EE5, AF_ADJUST_DOWN }, /* ụ */ + { 0x1EE6, AF_ADJUST_UP }, /* Ủ */ + { 0x1EE7, AF_ADJUST_UP }, /* ủ */ + { 0x1EE8, AF_ADJUST_UP | AF_IGNORE_CAPITAL_TOP }, /* Ứ */ + { 0x1EE9, AF_ADJUST_UP | AF_IGNORE_SMALL_TOP }, /* ứ */ + { 0x1EEA, AF_ADJUST_UP | AF_IGNORE_CAPITAL_TOP }, /* Ừ */ + { 0x1EEB, AF_ADJUST_UP | AF_IGNORE_SMALL_TOP }, /* ừ */ + { 0x1EEC, AF_ADJUST_UP | AF_IGNORE_CAPITAL_TOP }, /* Ử */ + { 0x1EED, AF_ADJUST_UP | AF_IGNORE_SMALL_TOP }, /* ử */ + { 0x1EEE, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP | AF_IGNORE_CAPITAL_TOP }, /* Ữ */ + { 0x1EEF, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP | AF_IGNORE_SMALL_TOP }, /* ữ */ + + { 0x1EF0, AF_ADJUST_DOWN | AF_IGNORE_CAPITAL_TOP }, /* Ự */ + { 0x1EF1, AF_ADJUST_DOWN | AF_IGNORE_SMALL_TOP }, /* ự */ + { 0x1EF2, AF_ADJUST_UP }, /* Ỳ */ + { 0x1EF3, AF_ADJUST_UP }, /* ỳ */ + { 0x1EF4, AF_ADJUST_DOWN }, /* Ỵ */ + { 0x1EF5, AF_ADJUST_DOWN }, /* ỵ */ + { 0x1EF6, AF_ADJUST_UP }, /* Ỷ */ + { 0x1EF7, AF_ADJUST_UP }, /* ỷ */ + { 0x1EF8, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* Ỹ */ + { 0x1EF9, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ỹ */ + + /* Greek Extended */ + { 0x1F00, AF_ADJUST_UP }, /* ἀ */ + { 0x1F01, AF_ADJUST_UP }, /* ἁ */ + { 0x1F02, AF_ADJUST_UP }, /* ἂ */ + { 0x1F03, AF_ADJUST_UP }, /* ἃ */ + { 0x1F04, AF_ADJUST_UP }, /* ἄ */ + { 0x1F05, AF_ADJUST_UP }, /* ἅ */ + { 0x1F06, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ἆ */ + { 0x1F07, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ἇ */ + + { 0x1F10, AF_ADJUST_UP }, /* ἐ */ + { 0x1F11, AF_ADJUST_UP }, /* ἑ */ + { 0x1F12, AF_ADJUST_UP }, /* ἒ */ + { 0x1F13, AF_ADJUST_UP }, /* ἓ */ + { 0x1F14, AF_ADJUST_UP }, /* ἔ */ + { 0x1F15, AF_ADJUST_UP }, /* ἕ */ + + { 0x1F20, AF_ADJUST_UP }, /* ἠ */ + { 0x1F21, AF_ADJUST_UP }, /* ἡ */ + { 0x1F22, AF_ADJUST_UP }, /* ἢ */ + { 0x1F23, AF_ADJUST_UP }, /* ἣ */ + { 0x1F24, AF_ADJUST_UP }, /* ἤ */ + { 0x1F25, AF_ADJUST_UP }, /* ἥ */ + { 0x1F26, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ἦ */ + { 0x1F27, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ἧ */ + + { 0x1F30, AF_ADJUST_UP }, /* ἰ */ + { 0x1F31, AF_ADJUST_UP }, /* ἱ */ + { 0x1F32, AF_ADJUST_UP }, /* ἲ */ + { 0x1F33, AF_ADJUST_UP }, /* ἳ */ + { 0x1F34, AF_ADJUST_UP }, /* ἴ */ + { 0x1F35, AF_ADJUST_UP }, /* ἵ */ + { 0x1F36, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ἶ */ + { 0x1F37, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ἷ */ + + { 0x1F40, AF_ADJUST_UP }, /* ὀ */ + { 0x1F41, AF_ADJUST_UP }, /* ὁ */ + { 0x1F42, AF_ADJUST_UP }, /* ὂ */ + { 0x1F43, AF_ADJUST_UP }, /* ὃ */ + { 0x1F44, AF_ADJUST_UP }, /* ὄ */ + { 0x1F45, AF_ADJUST_UP }, /* ὅ */ + + { 0x1F50, AF_ADJUST_UP }, /* ὐ */ + { 0x1F51, AF_ADJUST_UP }, /* ὑ */ + { 0x1F52, AF_ADJUST_UP }, /* ὒ */ + { 0x1F53, AF_ADJUST_UP }, /* ὓ */ + { 0x1F54, AF_ADJUST_UP }, /* ὔ */ + { 0x1F55, AF_ADJUST_UP }, /* ὕ */ + { 0x1F56, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ὖ */ + { 0x1F57, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ὗ */ + + { 0x1F60, AF_ADJUST_UP }, /* ὠ */ + { 0x1F61, AF_ADJUST_UP }, /* ὡ */ + { 0x1F62, AF_ADJUST_UP }, /* ὢ */ + { 0x1F63, AF_ADJUST_UP }, /* ὣ */ + { 0x1F64, AF_ADJUST_UP }, /* ὤ */ + { 0x1F65, AF_ADJUST_UP }, /* ὥ */ + { 0x1F66, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ὦ */ + { 0x1F67, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ὧ */ + + { 0x1F70, AF_ADJUST_UP }, /* ὰ */ + { 0x1F71, AF_ADJUST_UP }, /* ά */ + { 0x1F72, AF_ADJUST_UP }, /* ὲ */ + { 0x1F73, AF_ADJUST_UP }, /* έ */ + { 0x1F74, AF_ADJUST_UP }, /* ὴ */ + { 0x1F75, AF_ADJUST_UP }, /* ή */ + { 0x1F76, AF_ADJUST_UP }, /* ὶ */ + { 0x1F77, AF_ADJUST_UP }, /* ί */ + { 0x1F78, AF_ADJUST_UP }, /* ὸ */ + { 0x1F79, AF_ADJUST_UP }, /* ό */ + { 0x1F7A, AF_ADJUST_UP }, /* ὺ */ + { 0x1F7B, AF_ADJUST_UP }, /* ύ */ + { 0x1F7C, AF_ADJUST_UP }, /* ὼ */ + { 0x1F7D, AF_ADJUST_UP }, /* ώ */ + + { 0x1F80, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾀ */ + { 0x1F81, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾁ */ + { 0x1F82, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾂ */ + { 0x1F83, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾃ */ + { 0x1F84, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾄ */ + { 0x1F85, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾅ */ + { 0x1F86, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ᾆ */ + { 0x1F87, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ᾇ */ + { 0x1F88, AF_ADJUST_DOWN }, /* ᾈ */ + { 0x1F89, AF_ADJUST_DOWN }, /* ᾉ */ + { 0x1F8A, AF_ADJUST_DOWN }, /* ᾊ */ + { 0x1F8B, AF_ADJUST_DOWN }, /* ᾋ */ + { 0x1F8C, AF_ADJUST_DOWN }, /* ᾌ */ + { 0x1F8D, AF_ADJUST_DOWN }, /* ᾍ */ + { 0x1F8E, AF_ADJUST_DOWN }, /* ᾎ */ + { 0x1F8F, AF_ADJUST_DOWN }, /* ᾏ */ + + { 0x1F90, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾐ */ + { 0x1F91, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾑ */ + { 0x1F92, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾒ */ + { 0x1F93, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾓ */ + { 0x1F94, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾔ */ + { 0x1F95, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾕ */ + { 0x1F96, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ᾖ */ + { 0x1F97, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ᾗ */ + { 0x1F98, AF_ADJUST_DOWN }, /* ᾘ */ + { 0x1F99, AF_ADJUST_DOWN }, /* ᾙ */ + { 0x1F9A, AF_ADJUST_DOWN }, /* ᾚ */ + { 0x1F9B, AF_ADJUST_DOWN }, /* ᾛ */ + { 0x1F9C, AF_ADJUST_DOWN }, /* ᾜ */ + { 0x1F9D, AF_ADJUST_DOWN }, /* ᾝ */ + { 0x1F9E, AF_ADJUST_DOWN }, /* ᾞ */ + { 0x1F9F, AF_ADJUST_DOWN }, /* ᾟ */ + + { 0x1FA0, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾠ */ + { 0x1FA1, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾡ */ + { 0x1FA2, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾢ */ + { 0x1FA3, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾣ */ + { 0x1FA4, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾤ */ + { 0x1FA5, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾥ */ + { 0x1FA6, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ᾦ */ + { 0x1FA7, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ᾧ */ + { 0x1FA8, AF_ADJUST_DOWN }, /* ᾨ */ + { 0x1FA9, AF_ADJUST_DOWN }, /* ᾩ */ + { 0x1FAA, AF_ADJUST_DOWN }, /* ᾪ */ + { 0x1FAB, AF_ADJUST_DOWN }, /* ᾫ */ + { 0x1FAC, AF_ADJUST_DOWN }, /* ᾬ */ + { 0x1FAD, AF_ADJUST_DOWN }, /* ᾭ */ + { 0x1FAE, AF_ADJUST_DOWN }, /* ᾮ */ + { 0x1FAF, AF_ADJUST_DOWN }, /* ᾯ */ + + { 0x1FB0, AF_ADJUST_UP }, /* ᾰ */ + { 0x1FB1, AF_ADJUST_UP }, /* ᾱ */ + { 0x1FB2, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾲ */ + { 0x1FB3, AF_ADJUST_DOWN }, /* ᾳ */ + { 0x1FB4, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ᾴ */ + { 0x1FB6, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ᾶ */ + { 0x1FB7, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ᾷ */ + { 0x1FB8, AF_ADJUST_UP }, /* Ᾰ */ + { 0x1FB9, AF_ADJUST_UP }, /* Ᾱ */ + { 0x1FBC, AF_ADJUST_DOWN }, /* ᾼ */ + + { 0x1FC2, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ῂ */ + { 0x1FC3, AF_ADJUST_DOWN }, /* ῃ */ + { 0x1FC4, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ῄ */ + { 0x1FC6, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ῆ */ + { 0x1FC7, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ῇ */ + { 0x1FCC, AF_ADJUST_DOWN }, /* ῌ */ + + { 0x1FD0, AF_ADJUST_UP }, /* ῐ */ + { 0x1FD1, AF_ADJUST_UP }, /* ῑ */ + { 0x1FD2, AF_ADJUST_UP2 }, /* ῒ */ + { 0x1FD3, AF_ADJUST_UP2 }, /* ΐ */ + { 0x1FD6, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ῖ */ + { 0x1FD7, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ῗ */ + { 0x1FD8, AF_ADJUST_UP }, /* Ῐ */ + { 0x1FD9, AF_ADJUST_UP }, /* Ῑ */ + + { 0x1FE0, AF_ADJUST_UP }, /* ῠ */ + { 0x1FE1, AF_ADJUST_UP }, /* ῡ */ + { 0x1FE2, AF_ADJUST_UP2 }, /* ῢ */ + { 0x1FE3, AF_ADJUST_UP2 }, /* ΰ */ + { 0x1FE4, AF_ADJUST_UP }, /* ῤ */ + { 0x1FE5, AF_ADJUST_UP }, /* ῥ */ + { 0x1FE6, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ῦ */ + { 0x1FE7, AF_ADJUST_UP2 | AF_ADJUST_TILDE_TOP }, /* ῧ */ + { 0x1FE8, AF_ADJUST_UP }, /* Ῠ */ + { 0x1FE9, AF_ADJUST_UP }, /* Ῡ */ + { 0x1FF2, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ῲ */ + { 0x1FF3, AF_ADJUST_DOWN }, /* ῳ */ + { 0x1FF4, AF_ADJUST_UP | AF_ADJUST_DOWN }, /* ῴ */ + { 0x1FF6, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP }, /* ῶ */ + { 0x1FF7, AF_ADJUST_UP | AF_ADJUST_TILDE_TOP | AF_ADJUST_DOWN }, /* ῷ */ + { 0x1FFC, AF_ADJUST_DOWN }, /* ῼ */ + + /* General Punctuation */ + { 0x203C, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ‼ */ + { 0x203D, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ‽ */ + + { 0x2047, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ⁇ */ + { 0x2048, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ⁈ */ + { 0x2049, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ⁉ */ + + /* Superscripts and Subscripts */ + { 0x2071, AF_ADJUST_UP }, /* ⁱ */ + + /* Currency Symbols */ + { 0x20AB, AF_ADJUST_DOWN }, /* ₫ */ + + { 0x20C0, AF_ADJUST_DOWN }, /* ⃀ */ + + /* Number Forms */ + { 0x2170, AF_ADJUST_UP }, /* ⅰ */ + { 0x2171, AF_ADJUST_UP }, /* ⅱ */ + { 0x2172, AF_ADJUST_UP }, /* ⅲ */ + { 0x2173, AF_ADJUST_UP }, /* ⅳ */ + { 0x2175, AF_ADJUST_UP }, /* ⅵ */ + { 0x2176, AF_ADJUST_UP }, /* ⅶ */ + { 0x2177, AF_ADJUST_UP }, /* ⅷ */ + { 0x2178, AF_ADJUST_UP }, /* ⅸ */ + { 0x217A, AF_ADJUST_UP }, /* ⅺ */ + { 0x217B, AF_ADJUST_UP }, /* ⅻ */ + + /* Latin Extended-C */ + { 0x2C64, AF_IGNORE_CAPITAL_BOTTOM } , /* Ɽ */ + { 0x2C67, AF_IGNORE_CAPITAL_BOTTOM } , /* Ⱨ */ + { 0x2C68, AF_IGNORE_SMALL_BOTTOM } , /* ⱨ */ + { 0x2C69, AF_IGNORE_CAPITAL_BOTTOM } , /* Ⱪ */ + { 0x2C6A, AF_IGNORE_SMALL_BOTTOM } , /* ⱪ */ + { 0x2C6B, AF_IGNORE_CAPITAL_BOTTOM } , /* Ⱬ */ + { 0x2C6C, AF_IGNORE_SMALL_BOTTOM } , /* ⱬ */ + { 0x2C6E, AF_IGNORE_CAPITAL_BOTTOM } , /* Ɱ */ + + { 0x2C7C, AF_ADJUST_UP }, /* ⱼ */ + { 0x2C7E, AF_IGNORE_CAPITAL_BOTTOM } , /* Ȿ */ + { 0x2C7F, AF_IGNORE_CAPITAL_BOTTOM } , /* Ɀ */ + + /* Coptic */ + { 0x2CC2, AF_ADJUST_UP }, /* Ⳃ */ + { 0x2CC3, AF_ADJUST_UP }, /* ⳃ */ + + /* Supplemental Punctuation */ + { 0x2E18, AF_ADJUST_UP }, /* ⸘ */ + + { 0x2E2E, AF_ADJUST_UP | AF_ADJUST_NO_HEIGHT_CHECK }, /* ⸮ */ + + /* Cyrillic Extended-B */ + { 0xA640, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꙁ */ + { 0xA641, AF_IGNORE_SMALL_BOTTOM } , /* ꙁ */ + { 0xA642, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꙃ */ + { 0xA643, AF_IGNORE_SMALL_BOTTOM } , /* ꙃ */ + + { 0xA680, AF_IGNORE_CAPITAL_TOP } , /* Ꚁ */ + { 0xA681, AF_IGNORE_SMALL_TOP } , /* ꚁ */ + { 0xA688, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꚉ */ + { 0xA689, AF_IGNORE_SMALL_BOTTOM } , /* ꚉ */ + { 0xA68A, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꚋ */ + { 0xA68B, AF_IGNORE_SMALL_BOTTOM } , /* ꚋ */ + { 0xA68E, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꚏ */ + { 0xA68F, AF_IGNORE_SMALL_BOTTOM } , /* ꚏ */ + + { 0xA690, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꚑ */ + { 0xA691, AF_IGNORE_SMALL_BOTTOM } , /* ꚑ */ + { 0xA696, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꚗ */ + { 0xA697, AF_IGNORE_SMALL_BOTTOM } , /* ꚗ */ + + /* Latin Extended-D */ + { 0xA726, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꜧ */ + { 0xA727, AF_IGNORE_SMALL_BOTTOM } , /* ꜧ */ + + { 0xA756, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꝗ */ + { 0xA758, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꝙ */ + + { 0xA771, AF_IGNORE_SMALL_BOTTOM } , /* ꝱ */ + { 0xA772, AF_IGNORE_SMALL_BOTTOM } , /* ꝲ */ + { 0xA773, AF_IGNORE_SMALL_BOTTOM } , /* ꝳ */ + { 0xA774, AF_IGNORE_SMALL_BOTTOM } , /* ꝴ */ + { 0xA776, AF_IGNORE_SMALL_BOTTOM } , /* ꝶ */ + + { 0xA790, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꞑ */ + { 0xA791, AF_IGNORE_SMALL_BOTTOM } , /* ꞑ */ + { 0xA794, AF_IGNORE_SMALL_BOTTOM } , /* ꞔ */ + { 0xA795, AF_IGNORE_SMALL_BOTTOM } , /* ꞕ */ + + { 0xA7C0, AF_IGNORE_CAPITAL_TOP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ꟁ */ + { 0xA7C1, AF_IGNORE_SMALL_TOP | AF_IGNORE_SMALL_BOTTOM }, /* ꟁ */ + { 0xA7C4, AF_IGNORE_CAPITAL_BOTTOM } , /* Ꞔ */ + { 0xA7C5, AF_IGNORE_CAPITAL_BOTTOM } , /* Ʂ */ + { 0xA7C6, AF_IGNORE_CAPITAL_BOTTOM } , /* Ᶎ */ + { 0xA7CC, AF_IGNORE_CAPITAL_TOP | AF_IGNORE_CAPITAL_BOTTOM }, /* Ꟍ */ + { 0xA7CD, AF_IGNORE_SMALL_TOP | AF_IGNORE_SMALL_BOTTOM }, /* ꟍ */ + + /* Latin Extended-E */ + { 0xAB3C, AF_IGNORE_SMALL_BOTTOM } , /* ꬼ */ + + { 0xAB46, AF_IGNORE_SMALL_BOTTOM } , /* ꭆ */ + + { 0xAB5C, AF_IGNORE_SMALL_BOTTOM } , /* ꭜ */ + + { 0xAB66, AF_IGNORE_SMALL_BOTTOM } , /* ꭦ */ + { 0xAB67, AF_IGNORE_SMALL_BOTTOM } , /* ꭧ */ + }; + + + FT_LOCAL_DEF( FT_UInt32 ) + af_adjustment_database_lookup( FT_UInt32 codepoint ) + { + /* Binary search for database entry */ + FT_Offset low = 0; + FT_Offset high = AF_ADJUSTMENT_DATABASE_LENGTH - 1; + + + while ( high >= low ) + { + FT_Offset mid = ( low + high ) / 2; + FT_UInt32 mid_codepoint = adjustment_database[mid].codepoint; + + + if ( mid_codepoint < codepoint ) + low = mid + 1; + else if ( mid_codepoint > codepoint ) + high = mid - 1; + else + return adjustment_database[mid].flags; + } + + return 0; + } + + +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + + static FT_Error + add_substitute( FT_Int glyph_idx, + size_t value, + FT_UInt32 codepoint, + FT_Hash reverse_map, + FT_Hash subst_map, + FT_Memory memory ) + { + FT_Error error; + + FT_Int first_substitute = (FT_Int)( value & 0xFFFF ); + + FT_UInt used = reverse_map->used; + + + /* + OpenType features like 'unic' map lowercase letter glyphs to uppercase + forms (and vice versa), which could lead to the use of wrong entries + in the adjustment database. For this reason we don't overwrite, + prioritizing cmap entries. + + XXX Note, however, that this cannot cover all cases since there might + be contradictory entries for glyphs not in the cmap. A possible + solution might be to specially mark pairs of related lowercase and + uppercase characters in the adjustment database that have diacritics + on different vertical sides (for example, U+0122 'Ģ' and U+0123 'ģ'). + The auto-hinter could then perform a topological analysis to do the + right thing. + */ + error = ft_hash_num_insert_no_overwrite( first_substitute, codepoint, + reverse_map, memory ); + if ( error ) + return error; + + if ( reverse_map->used > used ) + { + size_t* subst = ft_hash_num_lookup( first_substitute, subst_map ); + + + if ( subst ) + { + error = add_substitute( first_substitute, *subst, codepoint, + reverse_map, subst_map, memory ); + if ( error ) + return error; + } + } + + /* The remaining substitutes. */ + if ( value & 0xFFFF0000U ) + { + FT_UInt num_substitutes = value >> 16; + + FT_UInt i; + + + for ( i = 1; i <= num_substitutes; i++ ) + { + FT_Int idx = glyph_idx + (FT_Int)( i << 16 ); + size_t* substitute = ft_hash_num_lookup( idx, subst_map ); + + + used = reverse_map->used; + + error = ft_hash_num_insert_no_overwrite( *substitute, + codepoint, + reverse_map, + memory ); + if ( error ) + return error; + + if ( reverse_map->used > used ) + { + size_t* subst = ft_hash_num_lookup( *substitute, subst_map ); + + + if ( subst ) + { + error = add_substitute( *substitute, *subst, codepoint, + reverse_map, subst_map, memory ); + if ( error ) + return error; + } + } + } + } + + return FT_Err_Ok; + } + +#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */ + + + /* Construct a 'reverse cmap' (i.e., a mapping from glyph indices to */ + /* character codes) for all glyphs that an input code point could turn */ + /* into. */ + /* */ + /* If HarfBuzz support is not available, this is the direct inversion */ + /* of the cmap table, otherwise the mapping gets extended with data */ + /* from the 'GSUB' table. */ + FT_LOCAL_DEF( FT_Error ) + af_reverse_character_map_new( FT_Hash *map, + AF_StyleMetrics metrics ) + { + FT_Error error; + + AF_FaceGlobals globals = metrics->globals; + FT_Face face = globals->face; + FT_Memory memory = face->memory; + + FT_CharMap old_charmap; + + FT_UInt32 codepoint; + FT_Offset i; + + + FT_TRACE4(( "af_reverse_character_map_new:" + " building reverse character map (style `%s')\n", + af_style_names[metrics->style_class->style] )); + + /* Search for a unicode charmap. */ + /* If there isn't one, create a blank map. */ + + /* Back up `face->charmap` because `find_unicode_charmap` sets it. */ + old_charmap = face->charmap; + + if ( ( error = find_unicode_charmap( face ) ) ) + goto Exit; + + *map = NULL; + if ( FT_QNEW( *map ) ) + goto Exit; + + error = ft_hash_num_init( *map, memory ); + if ( error ) + goto Exit; + + /* Initialize reverse cmap with data directly from the cmap table. */ + for ( i = 0; i < AF_ADJUSTMENT_DATABASE_LENGTH; i++ ) + { + FT_Int cmap_glyph; + + + /* + We cannot restrict `codepoint` to character ranges; we have no + control what data the script-specific portion of the GSUB table + actually holds. + + An example is `arial.ttf` version 7.00; in this font, there are + lookups for Cyrillic (lookup 43), Greek (lookup 44), and Latin + (lookup 45) that map capital letter glyphs to small capital glyphs. + It is tempting to expect that script-specific versions of the 'c2sc' + feature only use script-specific lookups. However, this is not the + case in this font: the feature uses all three lookups regardless of + the script. + + The auto-hinter, while assigning glyphs to styles, uses the first + coverage result it encounters for a particular glyph. For example, + if the coverage for Cyrillic is tested before Latin (as is currently + the case), glyphs without a cmap entry that are covered in 'c2sc' + are treated as Cyrillic. + + If we now look at glyph 3498, which is a small-caps version of the + Latin character 'A grave' (U+00C0, glyph 172), we can see that it is + registered as belonging to a Cyrillic style due to the algorithm + just described. As a result, checking only for characters from the + Latin range would miss this glyph; we thus have to test all + character codes in the database. + */ + codepoint = adjustment_database[i].codepoint; + + cmap_glyph = (FT_Int)FT_Get_Char_Index( face, codepoint ); + if ( cmap_glyph == 0 ) + continue; + + error = ft_hash_num_insert( cmap_glyph, codepoint, *map, memory ); + if ( error ) + goto Exit; + } + +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + + if ( ft_hb_enabled( globals ) ) + { + hb_font_t *hb_font; + hb_face_t *hb_face; + + hb_set_t *gsub_lookups; + hb_script_t script; + + unsigned int script_count = 1; + hb_tag_t script_tags[2] = { HB_TAG_NONE, HB_TAG_NONE }; + + FT_Hash subst_map = NULL; + + hb_codepoint_t idx; + FT_UInt hash_idx; + FT_Int glyph_idx; + size_t value; + + + /* No need to check whether HarfBuzz has allocation issues; */ + /* it continues to work in such cases and simply returns */ + /* 'empty' objects that do nothing. */ + + hb_font = globals->hb_font; + hb_face = hb( font_get_face )( hb_font ); + + gsub_lookups = hb( set_create )(); + + script = af_hb_scripts[metrics->style_class->script]; + + hb( ot_tags_from_script_and_language )( script, NULL, + &script_count, script_tags, + NULL, NULL ); + + /* Compute set of all script-specific GSUB lookups. */ + hb( ot_layout_collect_lookups )( hb_face, + HB_OT_TAG_GSUB, + script_tags, NULL, NULL, + gsub_lookups ); + +#ifdef FT_DEBUG_LEVEL_TRACE + { + FT_Bool have_idx = FALSE; + + + FT_TRACE4(( " GSUB lookups to check:\n" )); + + FT_TRACE4(( " " )); + idx = HB_SET_VALUE_INVALID; + while ( hb( set_next )( gsub_lookups, &idx ) ) + if ( globals->gsub_lookups_single_alternate[idx] ) + { + have_idx = TRUE; + FT_TRACE4(( " %u", idx )); + } + if ( !have_idx ) + FT_TRACE4(( " (none)" )); + FT_TRACE4(( "\n" )); + + FT_TRACE4(( "\n" )); + } +#endif + + if ( FT_QNEW( subst_map ) ) + goto Exit_HarfBuzz; + + error = ft_hash_num_init( subst_map, memory ); + if ( error ) + goto Exit_HarfBuzz; + + idx = HB_SET_VALUE_INVALID; + while ( hb( set_next )( gsub_lookups, &idx ) ) + { + FT_UInt32 offset = globals->gsub_lookups_single_alternate[idx]; + + + /* Put all substitutions into a single hash table. Note that */ + /* the hash values usually contain more than a single character */ + /* code; this can happen if different 'SingleSubst' subtables */ + /* map a given glyph index to different substitutions, or if */ + /* 'AlternateSubst' subtable entries are present. */ + if ( offset ) + af_map_lookup( globals, subst_map, offset ); + } + + /* + Now iterate over the collected substitution data in `subst_map` + (using recursion to resolve one-to-many mappings) and insert the + data into the reverse cmap. + + As an example, suppose we have the following cmap and substitution + data: + + cmap: X -> a + Y -> b + Z -> c + + substitutions: a -> b + b -> c, d + d -> e + + The reverse map now becomes as follows. + + a -> X + b -> Y + c -> Z (via cmap, ignoring mapping from 'b') + d -> Y (via 'b') + e -> Y (via 'b' and 'd') + */ + + hash_idx = 0; + while ( ft_hash_num_iterator( &hash_idx, + &glyph_idx, + &value, + subst_map ) ) + { + size_t* val; + + + /* Ignore keys that do not point to the first substitute. */ + if ( (FT_UInt)glyph_idx & 0xFFFF0000U ) + continue; + + /* Ignore glyph indices that are not related to accents. */ + val = ft_hash_num_lookup( glyph_idx, *map ); + if ( !val ) + continue; + + codepoint = *val; + + error = add_substitute( glyph_idx, value, codepoint, + *map, subst_map, memory ); + if ( error ) + break; + } + + Exit_HarfBuzz: + hb( set_destroy )( gsub_lookups ); + + ft_hash_num_free( subst_map, memory ); + FT_FREE( subst_map ); + + if ( error ) + goto Exit; + } + +#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */ + + FT_TRACE4(( " reverse character map built successfully" + " with %u entries\n", ( *map )->used )); + +#ifdef FT_DEBUG_LEVEL_TRACE + + { + FT_UInt cnt; + + + FT_TRACE7(( " gidx code flags\n" )); + /* " XXXXX 0xXXXX XXXXXXXXXXX..." */ + FT_TRACE7(( " ------------------------------\n" )); + + for ( cnt = 0; cnt < globals->glyph_count; cnt++ ) + { + size_t* val; + FT_UInt32 adj_type; + + const char* flag_names[] = + { + "up", /* AF_ADJUST_UP */ + "down", /* AF_ADJUST_DOWN */ + "double up", /* AF_ADJUST_UP2 */ + "double down", /* AF_ADJUST_DOWN2 */ + + "top tilde", /* AF_ADJUST_TILDE_TOP */ + "bottom tilde", /* AF_ADJUST_TILDE_BOTTOM */ + "below-top tilde", /* AF_ADJUST_TILDE_TOP2 */ + "above-bottom tilde", /* AF_ADJUST_TILDE_BOTTOM2 */ + + "ignore capital top", /* AF_IGNORE_CAPITAL_TOP */ + "ignore capital bottom", /* AF_IGNORE_CAPITAL_BOTTOM */ + "ignore small top", /* AF_IGNORE_SMALL_TOP */ + "ignore small bottom", /* AF_IGNORE_SMALL_BOTTOM */ + }; + size_t flag_names_size = sizeof ( flag_names ) / sizeof ( char* ); + + char flag_str[256]; + int need_comma; + + size_t j; + + + val = ft_hash_num_lookup( (FT_Int)cnt, *map ); + if ( !val ) + continue; + codepoint = *val; + + adj_type = af_adjustment_database_lookup( codepoint ); + if ( !adj_type ) + continue; + + flag_str[0] = '\0'; + need_comma = 0; + + for ( j = 0; j < flag_names_size; j++ ) + { + if ( adj_type & (1 << j ) ) + { + if ( !need_comma ) + need_comma = 1; + else + strcat( flag_str, ", " ); + strcat( flag_str, flag_names[j] ); + } + } + + FT_TRACE7(( " %5u 0x%04X %s\n", cnt, codepoint, flag_str )); + } + } + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + + Exit: + face->charmap = old_charmap; + + if ( error ) + { + FT_TRACE4(( " error while building reverse character map." + " Using blank map.\n" )); + + if ( *map ) + ft_hash_num_free( *map, memory ); + + FT_FREE( *map ); + *map = NULL; + return error; + } + + return FT_Err_Ok; + } + + + FT_LOCAL_DEF( FT_Error ) + af_reverse_character_map_done( FT_Hash map, + FT_Memory memory ) + { + if ( map ) + ft_hash_num_free( map, memory ); + FT_FREE( map ); + + return FT_Err_Ok; + } + + +/* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h new file mode 100644 index 00000000000..4837451ae4c --- /dev/null +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.h @@ -0,0 +1,130 @@ +/**************************************************************************** + * + * afadjust.h + * + * Auto-fitter routines to adjust components based on charcode (header). + * + * Copyright (C) 2023-2025 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * Written by Craig White . + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef AFADJUST_H_ +#define AFADJUST_H_ + +#include + +#include "afglobal.h" +#include "aftypes.h" + + +FT_BEGIN_HEADER + + /* + * Adjustment type flags. + * + * They also specify topological constraints that the auto-hinter relies + * on. For example, using `AF_ADJUST_UP` implies that we have two + * enclosing contours, one for the base glyph and one for the diacritic + * above, and no other contour inbetween or above. With 'enclosing' it is + * meant that such a contour can contain more inner contours. + * + */ + + /* Find the topmost contour and push it up until its lowest point is */ + /* one pixel above the highest point not enclosed by that contour. */ +#define AF_ADJUST_UP 0x01 + + /* Find the bottommost contour and push it down until its highest point */ + /* is one pixel below the lowest point not enclosed by that contour. */ +#define AF_ADJUST_DOWN 0x02 + + /* Find the contour below the topmost contour and push it up, together */ + /* with the topmost contour, until its lowest point is one pixel above */ + /* the highest point not enclosed by that contour. This flag is */ + /* mutually exclusive with `AF_ADJUST_UP`. */ +#define AF_ADJUST_UP2 0x04 + + /* Find the contour above the bottommost contour and push it down, */ + /* together with the bottommost contour, until its highest point is */ + /* one pixel below the lowest point not enclosed by that contour. */ + /* This flag is mutually exclusive with `AF_ADJUST_DOWN`. */ +#define AF_ADJUST_DOWN2 0x08 + + /* The topmost contour is a tilde. Enlarge it vertically so that it */ + /* stays legible at small sizes, not degenerating to a horizontal line. */ +#define AF_ADJUST_TILDE_TOP 0x10 + + /* The bottommost contour is a tilde. Enlarge it vertically so that it */ + /* stays legible at small sizes, not degenerating to a horizontal line. */ +#define AF_ADJUST_TILDE_BOTTOM 0x20 + + /* The contour below the topmost contour is a tilde. Enlarge it */ + /* vertically so that it stays legible at small sizes, not degenerating */ + /* to a horizontal line. To be used with `AF_ADJUST_UP2` only. */ +#define AF_ADJUST_TILDE_TOP2 0x40 + + /* The contour above the bottommost contour is a tilde. Enlarge it */ + /* vertically so that it stays legible at small sizes, not degenerating */ + /* to a horizontal line. To be used with `AF_ADJUST_DOWN2` only. */ +#define AF_ADJUST_TILDE_BOTTOM2 0x80 + + /* Make the auto-hinter ignore any diacritic (either a separate contour */ + /* or part of the base character outline) that is attached to the top */ + /* of an uppercase base character. */ +#define AF_IGNORE_CAPITAL_TOP 0x100 + + /* Make the auto-hinter ignore any diacritic (either a separate contour */ + /* or part of the base character outline) that is attached to the */ + /* bottom of an uppercase base character. */ +#define AF_IGNORE_CAPITAL_BOTTOM 0x200 + + /* Make the auto-hinter ignore any diacritic (either a separate contour */ + /* or part of the base character outline) that is attached to the top */ + /* of a lowercase base character. */ +#define AF_IGNORE_SMALL_TOP 0x400 + + /* Make the auto-hinter ignore any diacritic (either a separate contour */ + /* or part of the base character outline) that is attached to the */ + /* bottom of a lowercase base character. */ +#define AF_IGNORE_SMALL_BOTTOM 0x800 + + /* By default, the AF_ADJUST_XXX flags are applied only if diacritics */ + /* have a 'small' height (based on some heuristic checks). If this */ + /* flag is set, no such check is performed. */ +#define AF_ADJUST_NO_HEIGHT_CHECK 0x1000 + + /* No adjustment, i.e., no flag is set. */ +#define AF_ADJUST_NONE 0x00 + + + FT_LOCAL( FT_UInt32 ) + af_adjustment_database_lookup( FT_UInt32 codepoint ); + + /* Allocate and populate the reverse character map, */ + /* using the character map within the face. */ + FT_LOCAL( FT_Error ) + af_reverse_character_map_new( FT_Hash *map, + AF_StyleMetrics metrics ); + + /* Free the reverse character map. */ + FT_LOCAL( FT_Error ) + af_reverse_character_map_done( FT_Hash map, + FT_Memory memory ); + + +FT_END_HEADER + +#endif /* AFADJUST_H_ */ + + +/* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c index ea83969cdc9..a6219bdfe41 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -467,24 +467,24 @@ af_blue_stringsets[] = { /* */ - { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, { AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_ARABIC_BOTTOM, 0 }, { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM, 0 }, - { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, + { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_ARMENIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_AVESTAN_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -508,14 +508,14 @@ { AF_BLUE_STRING_CHAKMA_BOTTOM, 0 }, { AF_BLUE_STRING_CHAKMA_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 }, { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_CARIAN_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -527,24 +527,24 @@ { AF_BLUE_STRING_CHEROKEE_SMALL, 0 }, { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, { AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0 }, { AF_BLUE_STRING_CYPRIOT_SMALL, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_CYPRIOT_SMALL, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }, - { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }, + { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP | @@ -553,12 +553,12 @@ { AF_BLUE_STRING_DEVANAGARI_BASE, 0 }, { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, { AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -578,23 +578,23 @@ { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 }, + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GOTHIC_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 }, - { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, + { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_GREEK_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_GREEK_SMALL, 0 }, - { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_GREEK_SMALL, 0 }, + { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_GUJARATI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, { AF_BLUE_STRING_GUJARATI_BOTTOM, 0 }, @@ -643,45 +643,45 @@ { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_LAO_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }, - { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, + { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 }, - { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, + { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 }, - { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 }, - { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 }, + { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, + { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 }, - { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 }, + { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_LISU_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_MALAYALAM_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM, 0 }, - { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, + { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_MONGOLIAN_TOP_BASE, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -691,12 +691,12 @@ { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_NKO_BOTTOM, 0 }, + { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_NKO_BOTTOM, 0 }, { AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_NKO_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_OL_CHIKI, 0 }, @@ -704,15 +704,15 @@ { AF_BLUE_STRING_OLD_TURKIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 }, - { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 }, - { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM }, + { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 }, + { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_OSMANYA_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, @@ -723,13 +723,13 @@ { AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 }, { AF_BLUE_STRING_MAX, 0 }, - { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, - { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 }, - { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 }, + { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, + { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 }, + { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 }, { AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, - { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 }, - { AF_BLUE_STRING_MAX, 0 }, + AF_BLUE_PROPERTY_LATIN_X_HEIGHT }, + { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM }, + { AF_BLUE_STRING_MAX, 0 }, { AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }, { AF_BLUE_STRING_SINHALA_BOTTOM, 0 }, { AF_BLUE_STRING_SINHALA_DESCENDER, 0 }, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin index d2270fac744..786c6b3b9e6 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (body). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat index 88bab2632ab..f6e96ff8189 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat @@ -2,7 +2,7 @@ // // Auto-fitter data for blue strings. // -// Copyright (C) 2013-2024 by +// Copyright (C) 2013-2025 by // David Turner, Robert Wilhelm, and Werner Lemberg. // // This file is part of the FreeType project, and may only be used, @@ -699,12 +699,12 @@ AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN: AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: AF_BLUE_STRINGSET_ADLM - { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } { AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_ARAB { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -713,14 +713,14 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_ARMN - { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM, 0 } - { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } + { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_ARMENIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_AVST { AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -756,14 +756,14 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_CANS - { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 } { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_CARI { AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -781,12 +781,12 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_COPT - { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } { AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_CPRT { AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -796,13 +796,13 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_CYRL - { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_CYRILLIC_SMALL, 0 } - { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_CYRILLIC_SMALL, 0 } + { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_DEVA { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -815,12 +815,12 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_DSRT - { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } { AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_ETHI { AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -848,12 +848,12 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_GLAG - { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 } + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_GOTH { AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -861,14 +861,14 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_GREK - { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 } - { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } + { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_GREEK_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_GREEK_SMALL, 0 } - { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_GREEK_SMALL, 0 } + { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_GUJR { AF_BLUE_STRING_GUJARATI_TOP, AF_BLUE_PROPERTY_LATIN_TOP | @@ -935,34 +935,34 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_LATN - { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 } - { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } + { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_LATB - { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 } - { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } + { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 } - { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 } + { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_LATP - { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 } - { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } + { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 } - { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 } + { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_LISU { AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -975,15 +975,15 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_MEDF - { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM, 0 } - { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } + { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP } { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_MONG { AF_BLUE_STRING_MONGOLIAN_TOP_BASE, AF_BLUE_PROPERTY_LATIN_TOP } @@ -999,12 +999,12 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_NKOO - { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_NKO_BOTTOM, 0 } + { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_NKO_BOTTOM, 0 } { AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_NKO_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_NONE { AF_BLUE_STRING_MAX, 0 } @@ -1020,15 +1020,15 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_OSGE - { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 } - { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 } - { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 } - { AF_BLUE_STRING_MAX, 0 } + { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM } + { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 } + { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_OSMA { AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } @@ -1047,13 +1047,13 @@ AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN: { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_SHAW - { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } - { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 } - { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 } + { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP } + { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 } + { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 } { AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP | - AF_BLUE_PROPERTY_LATIN_X_HEIGHT } - { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 } - { AF_BLUE_STRING_MAX, 0 } + AF_BLUE_PROPERTY_LATIN_X_HEIGHT } + { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM } + { AF_BLUE_STRING_MAX, 0 } AF_BLUE_STRINGSET_SINH { AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP } diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h index 2aa9d0984ef..5bb8406dc2b 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h @@ -7,7 +7,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -314,14 +314,17 @@ FT_BEGIN_HEADER /* Properties are specific to a writing system. We assume that a given */ /* blue string can't be used in more than a single writing system, which */ /* is a safe bet. */ -#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */ +#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must be value 1 */ #define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 ) #define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 ) #define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 ) #define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 ) -#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */ -#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */ +#define AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM ( 1U << 5 ) +#define AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM ( 1U << 6 ) + +#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must be value 1 */ +#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must be value 2 */ #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin index 38031505a85..dbac14548d5 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin @@ -4,7 +4,7 @@ * * Auto-fitter data for blue strings (specification). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -99,14 +99,17 @@ FT_BEGIN_HEADER /* Properties are specific to a writing system. We assume that a given */ /* blue string can't be used in more than a single writing system, which */ /* is a safe bet. */ -#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must have value 1 */ +#define AF_BLUE_PROPERTY_LATIN_TOP ( 1U << 0 ) /* must be value 1 */ #define AF_BLUE_PROPERTY_LATIN_SUB_TOP ( 1U << 1 ) #define AF_BLUE_PROPERTY_LATIN_NEUTRAL ( 1U << 2 ) #define AF_BLUE_PROPERTY_LATIN_X_HEIGHT ( 1U << 3 ) #define AF_BLUE_PROPERTY_LATIN_LONG ( 1U << 4 ) -#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must have value 1 */ -#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must have value 2 */ +#define AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM ( 1U << 5 ) +#define AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM ( 1U << 6 ) + +#define AF_BLUE_PROPERTY_CJK_TOP ( 1U << 0 ) /* must be value 1 */ +#define AF_BLUE_PROPERTY_CJK_HORIZ ( 1U << 1 ) /* must be value 2 */ #define AF_BLUE_PROPERTY_CJK_RIGHT AF_BLUE_PROPERTY_CJK_TOP diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c index 869b60487c2..7086601838c 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (body). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -90,12 +90,8 @@ /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - void* shaper_buf; -#else FT_ULong shaper_buf_; void* shaper_buf = &shaper_buf_; -#endif const char* p; @@ -105,9 +101,8 @@ p = script_class->standard_charstring; -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - shaper_buf = af_shaper_buf_create( face ); -#endif + if ( ft_hb_enabled( metrics->root.globals ) ) + shaper_buf = af_shaper_buf_create( metrics->root.globals ); /* We check a list of standard characters. The first match wins. */ @@ -144,7 +139,7 @@ break; } - af_shaper_buf_destroy( face, shaper_buf ); + af_shaper_buf_destroy( metrics->root.globals, shaper_buf ); if ( !glyph_index ) goto Exit; @@ -152,7 +147,7 @@ if ( !glyph_index ) goto Exit; - FT_TRACE5(( "standard character: U+%04lX (glyph index %ld)\n", + FT_TRACE5(( "standard character: U+%04lX (glyph index %lu)\n", ch, glyph_index )); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); @@ -297,12 +292,8 @@ /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - void* shaper_buf; -#else FT_ULong shaper_buf_; void* shaper_buf = &shaper_buf_; -#endif /* we walk over the blue character strings as specified in the */ @@ -313,9 +304,8 @@ FT_TRACE5(( "==========================\n" )); FT_TRACE5(( "\n" )); -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - shaper_buf = af_shaper_buf_create( face ); -#endif + if ( ft_hb_enabled( metrics->root.globals ) ) + shaper_buf = af_shaper_buf_create( metrics->root.globals ); for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ ) { @@ -340,7 +330,7 @@ }; - FT_TRACE5(( "blue zone %d (%s):\n", + FT_TRACE5(( "blue zone %u (%s):\n", axis->blue_count, cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) | AF_CJK_IS_TOP_BLUE( bs ) ] )); @@ -553,7 +543,7 @@ } /* end for loop */ - af_shaper_buf_destroy( face, shaper_buf ); + af_shaper_buf_destroy( metrics->root.globals, shaper_buf ); FT_TRACE5(( "\n" )); @@ -572,23 +562,20 @@ /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - void* shaper_buf; -#else FT_ULong shaper_buf_; void* shaper_buf = &shaper_buf_; -#endif /* in all supported charmaps, digits have character codes 0x30-0x39 */ const char digits[] = "0 1 2 3 4 5 6 7 8 9"; const char* p; + FT_UNUSED( face ); + p = digits; -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - shaper_buf = af_shaper_buf_create( face ); -#endif + if ( ft_hb_enabled( metrics->root.globals ) ) + shaper_buf = af_shaper_buf_create( metrics->root.globals ); while ( *p ) { @@ -624,7 +611,7 @@ } } - af_shaper_buf_destroy( face, shaper_buf ); + af_shaper_buf_destroy( metrics->root.globals, shaper_buf ); metrics->root.digits_have_same_width = same_width; } @@ -710,7 +697,7 @@ FT_Pos delta1, delta2; - blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); + blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); /* shoot is under shoot for cjk */ delta1 = FT_DivFix( blue->ref.fit, scale ) - blue->shoot.org; @@ -736,7 +723,7 @@ blue->shoot.fit = blue->ref.fit - delta2; - FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n", + FT_TRACE5(( ">> active cjk blue zone %c%u[%ld/%ld]:\n", ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V', nn, blue->ref.org, blue->shoot.org )); FT_TRACE5(( " ref: cur=%.2f fit=%.2f\n", @@ -1378,7 +1365,7 @@ } - /* Initalize hinting engine. */ + /* Initialize hinting engine. */ FT_LOCAL_DEF( FT_Error ) af_cjk_hints_init( AF_GlyphHints hints, @@ -2185,7 +2172,7 @@ af_cjk_align_edge_points( AF_GlyphHints hints, AF_Dimension dim ) { - AF_AxisHints axis = & hints->axis[dim]; + AF_AxisHints axis = &hints->axis[dim]; AF_Edge edges = axis->edges; AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); AF_Edge edge; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h index bc5aaf12e6e..bd1b39358e0 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for CJK writing system (specification). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h index 7980cf2e979..b93bcd1a2c5 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h @@ -4,7 +4,7 @@ * * Auto-fitter coverages (specification only). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c index ad667d2edc7..8613544f913 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (body). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h index 613c2f88a38..78a79439d95 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h @@ -5,7 +5,7 @@ * Auto-fitter dummy routines to be used if no hinting should be * performed (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h index ae584ff06db..f3093fc90df 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h @@ -4,7 +4,7 @@ * * Autofitter error codes (specification only). * - * Copyright (C) 2005-2024 by + * Copyright (C) 2005-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c index b7403fa65e1..e74d8141161 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c @@ -4,7 +4,7 @@ * * Auto-fitter routines to compute global hinting values (body). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -22,6 +22,11 @@ #include "afws-decl.h" #include +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ +# include "afgsub.h" +# include "ft-hb-ft.h" +#endif + /************************************************************************** * @@ -184,7 +189,7 @@ if ( gindex != 0 && gindex < globals->glyph_count && ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED ) - gstyles[gindex] = ss; + gstyles[gindex] = ss | AF_HAS_CMAP_ENTRY; for (;;) { @@ -195,7 +200,7 @@ if ( gindex < globals->glyph_count && ( gstyles[gindex] & AF_STYLE_MASK ) == AF_STYLE_UNASSIGNED ) - gstyles[gindex] = ss; + gstyles[gindex] = ss | AF_HAS_CMAP_ENTRY; } } @@ -301,7 +306,7 @@ if ( !( count % 10 ) ) FT_TRACE4(( " " )); - FT_TRACE4(( " %d", idx )); + FT_TRACE4(( " %u", idx )); count++; if ( !( count % 10 ) ) @@ -356,8 +361,21 @@ globals->scale_down_factor = 0; #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - globals->hb_font = hb_ft_font_create_( face, NULL ); - globals->hb_buf = hb_buffer_create(); + if ( ft_hb_enabled ( globals ) ) + { + globals->hb_font = ft_hb_ft_font_create( globals ); + globals->hb_buf = hb( buffer_create )(); + + af_parse_gsub( globals ); + } + else + { + globals->hb_font = NULL; + globals->hb_buf = NULL; + + globals->gsub = NULL; + globals->gsub_lookups_single_alternate = NULL; + } #endif error = af_face_globals_compute_style_coverage( globals ); @@ -405,8 +423,14 @@ } #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - hb_font_destroy( globals->hb_font ); - hb_buffer_destroy( globals->hb_buf ); + if ( ft_hb_enabled ( globals ) ) + { + hb( font_destroy )( globals->hb_font ); + hb( buffer_destroy )( globals->hb_buf ); + + FT_FREE( globals->gsub ); + FT_FREE( globals->gsub_lookups_single_alternate ); + } #endif /* no need to free `globals->glyph_styles'; */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h index ddb54c89b27..362f56e290b 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h @@ -5,7 +5,7 @@ * Auto-fitter routines to compute global hinting values * (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -73,15 +73,17 @@ FT_BEGIN_HEADER /* default script for OpenType; ignored if HarfBuzz isn't used */ #define AF_SCRIPT_DEFAULT AF_SCRIPT_LATN - /* a bit mask for AF_DIGIT and AF_NONBASE */ -#define AF_STYLE_MASK 0x3FFF + /* a bit mask for AF_DIGIT, AF_NONBASE, and AF_HAS_CMAP_ENTRY */ +#define AF_STYLE_MASK 0x1FFF /* an uncovered glyph */ #define AF_STYLE_UNASSIGNED AF_STYLE_MASK - /* if this flag is set, we have an ASCII digit */ + /* if this flag is set, we have an ASCII digit */ #define AF_DIGIT 0x8000U /* if this flag is set, we have a non-base character */ #define AF_NONBASE 0x4000U + /* if this flag is set, the glyph has a (direct) cmap entry */ +#define AF_HAS_CMAP_ENTRY 0x2000U /* `increase-x-height' property */ #define AF_PROP_INCREASE_X_HEIGHT_MIN 6 @@ -111,6 +113,11 @@ FT_BEGIN_HEADER #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ hb_font_t* hb_font; hb_buffer_t* hb_buf; /* for feature comparison */ + + /* The GSUB table. */ + FT_Byte* gsub; + /* Lookup offsets, with only SingleSubst and AlternateSubst non-NULL. */ + FT_UInt32* gsub_lookups_single_alternate; #endif /* per-face auto-hinter properties */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c index 96ffe343aa4..11faa655f62 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (body). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -840,6 +840,10 @@ if ( hints->contours != hints->embedded.contours ) FT_FREE( hints->contours ); + if ( hints->contour_y_minima != hints->embedded.contour_y_minima ) + FT_FREE( hints->contour_y_minima ); + if ( hints->contour_y_maxima != hints->embedded.contour_y_maxima ) + FT_FREE( hints->contour_y_maxima ); hints->max_contours = 0; hints->num_contours = 0; @@ -896,19 +900,30 @@ { if ( !hints->contours ) { - hints->contours = hints->embedded.contours; + hints->contours = hints->embedded.contours; + hints->contour_y_minima = hints->embedded.contour_y_minima; + hints->contour_y_maxima = hints->embedded.contour_y_maxima; + hints->max_contours = AF_CONTOURS_EMBEDDED; } } else if ( new_max > old_max ) { if ( hints->contours == hints->embedded.contours ) - hints->contours = NULL; + { + hints->contours = NULL; + hints->contour_y_minima = NULL; + hints->contour_y_maxima = NULL; + } new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */ if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) ) goto Exit; + if ( FT_RENEW_ARRAY( hints->contour_y_minima, old_max, new_max ) ) + goto Exit; + if ( FT_RENEW_ARRAY( hints->contour_y_maxima, old_max, new_max ) ) + goto Exit; hints->max_contours = new_max; } @@ -1324,7 +1339,7 @@ af_glyph_hints_align_edge_points( AF_GlyphHints hints, AF_Dimension dim ) { - AF_AxisHints axis = & hints->axis[dim]; + AF_AxisHints axis = &hints->axis[dim]; AF_Segment segments = axis->segments; AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments ); AF_Segment seg; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h index 76fe83006a5..46b3ed3366f 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -222,6 +222,9 @@ FT_BEGIN_HEADER /* the distance to the next point is very small */ #define AF_FLAG_NEAR ( 1U << 5 ) + /* prevent the auto-hinter from adding such a point to a segment */ +#define AF_FLAG_IGNORE ( 1U << 6 ) + /* edge hint flags */ #define AF_EDGE_NORMAL 0 @@ -229,6 +232,7 @@ FT_BEGIN_HEADER #define AF_EDGE_SERIF ( 1U << 1 ) #define AF_EDGE_DONE ( 1U << 2 ) #define AF_EDGE_NEUTRAL ( 1U << 3 ) /* edge aligns to a neutral blue zone */ +#define AF_EDGE_NO_BLUE ( 1U << 4 ) /* do not align edge to blue zone */ typedef struct AF_PointRec_* AF_Point; @@ -303,6 +307,7 @@ FT_BEGIN_HEADER } AF_EdgeRec; + #define AF_SEGMENTS_EMBEDDED 18 /* number of embedded segments */ #define AF_EDGES_EMBEDDED 12 /* number of embedded edges */ @@ -346,9 +351,11 @@ FT_BEGIN_HEADER FT_Int num_points; /* number of used points */ AF_Point points; /* points array */ - FT_Int max_contours; /* number of allocated contours */ - FT_Int num_contours; /* number of used contours */ - AF_Point* contours; /* contours array */ + FT_Int max_contours; /* number of allocated contours */ + FT_Int num_contours; /* number of used contours */ + AF_Point* contours; /* contours array */ + FT_Pos* contour_y_minima; /* array with y maxima of contours */ + FT_Pos* contour_y_maxima; /* array with y minima of contours */ AF_AxisHintsRec axis[AF_DIMENSION_MAX]; @@ -357,11 +364,13 @@ FT_BEGIN_HEADER /* implementations */ AF_StyleMetrics metrics; - /* Two arrays to avoid allocation penalty. */ + /* Some arrays to avoid allocation penalty. */ /* The `embedded' structure must be the last element! */ struct { AF_Point contours[AF_CONTOURS_EMBEDDED]; + FT_Pos contour_y_minima[AF_CONTOURS_EMBEDDED]; + FT_Pos contour_y_maxima[AF_CONTOURS_EMBEDDED]; AF_PointRec points[AF_POINTS_EMBEDDED]; } embedded; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c index c6d23efd86f..a2cd14f8817 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for Indic writing system (body). * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * Rahul Bhalerao , . * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h index a7f73f25153..a2e825e9f86 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for Indic writing system * (specification). * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * Rahul Bhalerao , . * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c index 89287f7ea5a..cb5667ff793 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c @@ -4,7 +4,7 @@ * * Auto-fitter hinting routines for latin writing system (body). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -22,6 +22,7 @@ #include "afglobal.h" #include "aflatin.h" #include "aferrors.h" +#include "afadjust.h" /************************************************************************** @@ -81,12 +82,8 @@ /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - void* shaper_buf; -#else FT_ULong shaper_buf_; void* shaper_buf = &shaper_buf_; -#endif const char* p; @@ -97,9 +94,9 @@ p = script_class->standard_charstring; -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - shaper_buf = af_shaper_buf_create( face ); -#endif + if ( ft_hb_enabled ( metrics->root.globals ) ) + shaper_buf = af_shaper_buf_create( metrics->root.globals ); + /* * We check a list of standard characters to catch features like * `c2sc' (small caps from caps) that don't contain lowercase letters @@ -140,7 +137,7 @@ break; } - af_shaper_buf_destroy( face, shaper_buf ); + af_shaper_buf_destroy( metrics->root.globals, shaper_buf ); if ( !glyph_index ) { @@ -149,7 +146,7 @@ goto Exit; } - FT_TRACE5(( "standard character: U+%04lX (glyph index %ld)\n", + FT_TRACE5(( "standard character: U+%04lX (glyph index %lu)\n", ch, glyph_index )); error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); @@ -334,12 +331,8 @@ /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - void* shaper_buf; -#else FT_ULong shaper_buf_; void* shaper_buf = &shaper_buf_; -#endif /* we walk over the blue character strings as specified in the */ @@ -349,9 +342,8 @@ FT_TRACE5(( "============================\n" )); FT_TRACE5(( "\n" )); -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - shaper_buf = af_shaper_buf_create( face ); -#endif + if ( ft_hb_enabled ( metrics->root.globals ) ) + shaper_buf = af_shaper_buf_create( metrics->root.globals ); for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ ) { @@ -367,7 +359,7 @@ FT_Bool have_flag = 0; - FT_TRACE5(( "blue zone %d", axis->blue_count )); + FT_TRACE5(( "blue zone %u", axis->blue_count )); if ( bs->properties ) { @@ -407,6 +399,20 @@ FT_TRACE5(( "long" )); } + if ( AF_LATIN_IS_CAPITAL_BOTTOM_BLUE( bs ) ) + { + if ( have_flag ) + FT_TRACE5(( ", " )); + FT_TRACE5(( "capital bottom" )); + } + + if ( AF_LATIN_IS_SMALL_BOTTOM_BLUE( bs ) ) + { + if ( have_flag ) + FT_TRACE5(( ", " )); + FT_TRACE5(( "small bottom" )); + } + FT_TRACE5(( ")" )); } @@ -454,9 +460,9 @@ } if ( AF_LATIN_IS_TOP_BLUE( bs ) ) - best_y_extremum = FT_INT_MIN; + best_y_extremum = FT_LONG_MIN; else - best_y_extremum = FT_INT_MAX; + best_y_extremum = FT_LONG_MAX; /* iterate over all glyph elements of the character cluster */ /* and get the data of the `biggest' one */ @@ -487,7 +493,7 @@ if ( num_idx == 1 ) FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch )); else - FT_TRACE5(( " component %d of cluster starting with U+%04lX" + FT_TRACE5(( " component %u of cluster starting with U+%04lX" " contains no (usable) outlines\n", i, ch )); #endif continue; @@ -825,7 +831,7 @@ if ( num_idx == 1 ) FT_TRACE5(( " U+%04lX: best_y = %5ld", ch, best_y )); else - FT_TRACE5(( " component %d of cluster starting with U+%04lX:" + FT_TRACE5(( " component %u of cluster starting with U+%04lX:" " best_y = %5ld", i, ch, best_y )); #endif @@ -879,8 +885,8 @@ } /* end for loop */ - if ( !( best_y_extremum == FT_INT_MIN || - best_y_extremum == FT_INT_MAX ) ) + if ( !( best_y_extremum == FT_LONG_MIN || + best_y_extremum == FT_LONG_MAX ) ) { if ( best_round ) rounds[num_rounds++] = best_y_extremum; @@ -959,6 +965,10 @@ blue->flags |= AF_LATIN_BLUE_SUB_TOP; if ( AF_LATIN_IS_NEUTRAL_BLUE( bs ) ) blue->flags |= AF_LATIN_BLUE_NEUTRAL; + if ( AF_LATIN_IS_CAPITAL_BOTTOM_BLUE( bs ) ) + blue->flags |= AF_LATIN_BLUE_BOTTOM; + if ( AF_LATIN_IS_SMALL_BOTTOM_BLUE( bs ) ) + blue->flags |= AF_LATIN_BLUE_BOTTOM_SMALL; /* * The following flag is used later to adjust the y and x scales @@ -973,7 +983,7 @@ } /* end for loop */ - af_shaper_buf_destroy( face, shaper_buf ); + af_shaper_buf_destroy( metrics->root.globals, shaper_buf ); if ( axis->blue_count ) { @@ -1070,23 +1080,20 @@ /* If HarfBuzz is not available, we need a pointer to a single */ /* unsigned long value. */ -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - void* shaper_buf; -#else FT_ULong shaper_buf_; void* shaper_buf = &shaper_buf_; -#endif /* in all supported charmaps, digits have character codes 0x30-0x39 */ const char digits[] = "0 1 2 3 4 5 6 7 8 9"; const char* p; + FT_UNUSED( face ); + p = digits; -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - shaper_buf = af_shaper_buf_create( face ); -#endif + if ( ft_hb_enabled ( metrics->root.globals ) ) + shaper_buf = af_shaper_buf_create( metrics->root.globals ); while ( *p ) { @@ -1122,7 +1129,7 @@ } } - af_shaper_buf_destroy( face, shaper_buf ); + af_shaper_buf_destroy( metrics->root.globals, shaper_buf ); metrics->root.digits_have_same_width = same_width; } @@ -1155,6 +1162,9 @@ af_latin_metrics_check_digits( metrics, face ); } + af_reverse_character_map_new( &metrics->root.reverse_charmap, + &metrics->root ); + Exit: face->charmap = oldmap; return error; @@ -1263,7 +1273,7 @@ max_height = FT_MAX( max_height, -Axis->blues[nn].descender ); } - dist = FT_MulFix( max_height, new_scale - scale ); + dist = FT_MulFix( max_height, new_scale - scale ); if ( -128 < dist && dist < 128 ) { @@ -1466,13 +1476,13 @@ AF_LatinBlue blue = &axis->blues[nn]; - FT_TRACE5(( " reference %d: %ld scaled to %.2f%s\n", + FT_TRACE5(( " reference %u: %ld scaled to %.2f%s\n", nn, blue->ref.org, (double)blue->ref.fit / 64, ( blue->flags & AF_LATIN_BLUE_ACTIVE ) ? "" : " (inactive)" )); - FT_TRACE5(( " overshoot %d: %ld scaled to %.2f%s\n", + FT_TRACE5(( " overshoot %u: %ld scaled to %.2f%s\n", nn, blue->shoot.org, (double)blue->shoot.fit / 64, @@ -1484,6 +1494,17 @@ } + FT_CALLBACK_DEF( void ) + af_latin_metrics_done( AF_StyleMetrics metrics_ ) + { + AF_LatinMetrics metrics = (AF_LatinMetrics)metrics_; + + + af_reverse_character_map_done( metrics->root.reverse_charmap, + metrics->root.globals->face->memory ); + } + + /* Scale global values in both directions. */ FT_LOCAL_DEF( void ) @@ -1617,7 +1638,8 @@ FT_Pos prev_max_on_coord = max_on_coord; - if ( FT_ABS( last->out_dir ) == major_dir && + if ( !( point->flags & AF_FLAG_IGNORE ) && + FT_ABS( last->out_dir ) == major_dir && FT_ABS( point->out_dir ) == major_dir ) { /* we are already on an edge, try to locate its start */ @@ -1676,13 +1698,17 @@ max_on_coord = v; } - if ( point->out_dir != segment_dir || point == last ) + if ( point->flags & AF_FLAG_IGNORE || + point->out_dir != segment_dir || + point == last ) { /* check whether the new segment's start point is identical to */ /* the previous segment's end point; for example, this might */ /* happen for spikes */ - if ( !prev_segment || segment->first != prev_segment->last ) + if ( point->flags & AF_FLAG_IGNORE || + !prev_segment || + segment->first != prev_segment->last ) { /* points are different: we are just leaving an edge, thus */ /* record a new segment */ @@ -1842,7 +1868,8 @@ /* if we are not on an edge, check whether the major direction */ /* coincides with the current point's `out' direction, or */ /* whether we have a single-point contour */ - if ( !on_edge && + if ( !( point->flags & AF_FLAG_IGNORE ) && + !on_edge && ( FT_ABS( point->out_dir ) == major_dir || point == point->prev ) ) { @@ -2521,6 +2548,9 @@ FT_Pos best_dist; /* initial threshold */ + if ( edge->flags & AF_EDGE_NO_BLUE ) + continue; + /* compute the initial threshold as a fraction of the EM size */ /* (the value 40 is heuristic) */ best_dist = FT_MulFix( metrics->units_per_em / 40, scale ); @@ -2610,7 +2640,7 @@ } - /* Initalize hinting engine. */ + /* Initialize hinting engine. */ static FT_Error af_latin_hints_init( AF_GlyphHints hints, @@ -2737,6 +2767,1192 @@ } +#undef FT_COMPONENT +#define FT_COMPONENT afadjust + + + static void + af_move_contour_vertically( AF_Point contour, + FT_Int movement ) + { + AF_Point point = contour; + AF_Point first_point = point; + + + if ( point ) + { + do + { + point->y += movement; + point = point->next; + + } while ( point != first_point ); + } + } + + + /* Move all contours higher than `limit` by `delta`. */ + static void + af_move_contours_up( AF_GlyphHints hints, + FT_Pos limit, + FT_Pos delta ) + { + FT_Int contour; + + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos min_y = hints->contour_y_minima[contour]; + FT_Pos max_y = hints->contour_y_maxima[contour]; + + + if ( min_y < max_y && + min_y > limit ) + af_move_contour_vertically( hints->contours[contour], + delta ); + } + } + + + static void + af_move_contours_down( AF_GlyphHints hints, + FT_Pos limit, + FT_Pos delta ) + { + FT_Int contour; + + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos min_y = hints->contour_y_minima[contour]; + FT_Pos max_y = hints->contour_y_maxima[contour]; + + + if ( min_y < max_y && + max_y < limit ) + af_move_contour_vertically( hints->contours[contour], + -delta ); + } + } + + + /* Compute vertical extrema of all contours and store them in the */ + /* `contour_y_minima` and `contour_y_maxima` arrays of `hints`. */ + static void + af_compute_vertical_extrema( AF_GlyphHints hints ) + { + FT_Int contour; + + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos min_y = FT_LONG_MAX; + FT_Pos max_y = FT_LONG_MIN; + + AF_Point first_point = hints->contours[contour]; + AF_Point point = first_point; + + + if ( !first_point || first_point->next->next == first_point ) + goto End_loop; + + do + { + if ( point->y < min_y ) + min_y = point->y; + if ( point->y > max_y ) + max_y = point->y; + + point = point->next; + + } while ( point != first_point ); + + End_loop: + hints->contour_y_minima[contour] = min_y; + hints->contour_y_maxima[contour] = max_y; + } + } + + + static FT_Int + af_find_highest_contour( AF_GlyphHints hints ) + { + FT_Int highest_contour = 0; + FT_Pos highest_min_y = FT_LONG_MAX; + FT_Pos highest_max_y = FT_LONG_MIN; + + FT_Int contour; + + + /* At this point we have one 'lower' (usually the base glyph) */ + /* and one 'upper' object (usually the diacritic glyph). If */ + /* there are more contours, they must be enclosed within either */ + /* 'lower' or 'upper'. To find this enclosing 'upper' contour */ + /* it is thus sufficient to search for the contour with the */ + /* highest y maximum value. */ + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos current_min_y = hints->contour_y_minima[contour]; + FT_Pos current_max_y = hints->contour_y_maxima[contour]; + + + /* If we have two contours with the same maximum value, take */ + /* the one that has a smaller height. */ + if ( current_max_y > highest_max_y || + ( current_max_y == highest_max_y && + current_min_y > highest_min_y ) ) + { + highest_min_y = current_min_y; + highest_max_y = current_max_y; + highest_contour = contour; + } + } + + return highest_contour; + } + + + static FT_Int + af_find_second_highest_contour( AF_GlyphHints hints ) + { + FT_Int highest_contour; + FT_Pos highest_min_y; + + FT_Int second_highest_contour = 0; + FT_Pos second_highest_max_y = FT_LONG_MIN; + + FT_Int contour; + + + if ( hints->num_contours < 3 ) + return 0; + + highest_contour = af_find_highest_contour( hints ); + highest_min_y = hints->contour_y_minima[highest_contour]; + + /* Search the contour with the largest vertical maximum that has a */ + /* vertical minimum lower than the vertical minimum of the topmost */ + /* contour. */ + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos current_min_y; + FT_Pos current_max_y; + + + if ( contour == highest_contour ) + continue; + + current_min_y = hints->contour_y_minima[contour]; + current_max_y = hints->contour_y_maxima[contour]; + + if ( current_max_y > second_highest_max_y && + current_min_y < highest_min_y ) + { + second_highest_max_y = current_max_y; + second_highest_contour = contour; + } + } + + return second_highest_contour; + } + + + static FT_Int + af_find_lowest_contour( AF_GlyphHints hints ) + { + FT_Int lowest_contour = 0; + FT_Pos lowest_min_y = FT_LONG_MAX; + FT_Pos lowest_max_y = FT_LONG_MIN; + + FT_Int contour; + + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos current_min_y = hints->contour_y_minima[contour]; + FT_Pos current_max_y = hints->contour_y_maxima[contour]; + + + if ( current_min_y < lowest_min_y || + ( current_min_y == lowest_min_y && + current_max_y < lowest_max_y ) ) + { + lowest_min_y = current_min_y; + lowest_max_y = current_max_y; + lowest_contour = contour; + } + } + + return lowest_contour; + } + + + static FT_Int + af_find_second_lowest_contour( AF_GlyphHints hints ) + { + FT_Int lowest_contour; + FT_Pos lowest_max_y; + + FT_Int second_lowest_contour = 0; + FT_Pos second_lowest_min_y = FT_LONG_MAX; + + FT_Int contour; + + + if ( hints->num_contours < 3 ) + return 0; + + lowest_contour = af_find_lowest_contour( hints ); + lowest_max_y = hints->contour_y_maxima[lowest_contour]; + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos current_min_y; + FT_Pos current_max_y; + + + if ( contour == lowest_contour ) + continue; + + current_min_y = hints->contour_y_minima[contour]; + current_max_y = hints->contour_y_maxima[contour]; + + if ( current_min_y < second_lowest_min_y && + current_max_y > lowest_max_y ) + { + second_lowest_min_y = current_min_y; + second_lowest_contour = contour; + } + } + + return second_lowest_contour; + } + + + /* While aligning edges to blue zones, make the auto-hinter */ + /* ignore the ones that are higher than `pos`. */ + static void + af_prevent_top_blue_alignment( AF_GlyphHints hints, + FT_Pos pos ) + { + AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT]; + + AF_Edge edges = axis->edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); + AF_Edge edge; + + + for ( edge = edges; edge < edge_limit; edge++ ) + if ( edge->pos > pos ) + edge->flags |= AF_EDGE_NO_BLUE; + } + + + static void + af_prevent_bottom_blue_alignment( AF_GlyphHints hints, + FT_Pos pos ) + { + AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT]; + + AF_Edge edges = axis->edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); + AF_Edge edge; + + + for ( edge = edges; edge < edge_limit; edge++ ) + if ( edge->pos < pos ) + edge->flags |= AF_EDGE_NO_BLUE; + } + + + static void + af_latin_get_base_glyph_blues( AF_GlyphHints hints, + FT_Bool is_capital, + AF_LatinBlue* top, + AF_LatinBlue* bottom ) + { + AF_LatinMetrics metrics = (AF_LatinMetrics)hints->metrics; + AF_LatinAxis axis = &metrics->axis[AF_DIMENSION_VERT]; + + FT_UInt top_flag; + FT_UInt bottom_flag; + + FT_UInt i; + + + top_flag = is_capital ? AF_LATIN_BLUE_TOP + : AF_LATIN_BLUE_ADJUSTMENT; + top_flag |= AF_LATIN_BLUE_ACTIVE; + + for ( i = 0; i < axis->blue_count; i++ ) + if ( ( axis->blues[i].flags & top_flag ) == top_flag ) + break; + if ( i < axis->blue_count ) + *top = &axis->blues[i]; + + bottom_flag = is_capital ? AF_LATIN_BLUE_BOTTOM + : AF_LATIN_BLUE_BOTTOM_SMALL; + bottom_flag |= AF_LATIN_BLUE_ACTIVE; + + for ( i = 0; i < axis->blue_count; i++ ) + if ( ( axis->blues[i].flags & bottom_flag ) == bottom_flag ) + break; + if ( i < axis->blue_count ) + *bottom = &axis->blues[i]; + } + + + /* Make the auto-hinter ignore top blue zones while aligning edges. */ + /* This affects everything that is higher than a vertical position */ + /* based on the lowercase or uppercase top and bottom blue zones */ + /* (depending on `is_capital`). */ + static void + af_latin_ignore_top( AF_GlyphHints hints, + AF_LatinBlue top_blue, + AF_LatinBlue bottom_blue ) + { + FT_Pos base_glyph_height; + FT_Pos limit; + + + /* Ignore blue zones that are higher than a heuristic threshold */ + /* (value 7 corresponds to approx. 14%, which should be sufficient */ + /* to exceed the height of uppercase serifs. We also add a quarter */ + /* of a pixel as a safety measure. */ + base_glyph_height = top_blue->shoot.cur - bottom_blue->shoot.cur; + limit = top_blue->shoot.cur + base_glyph_height / 7 + 16; + + af_prevent_top_blue_alignment( hints, limit ); + } + + + static void + af_latin_ignore_bottom( AF_GlyphHints hints, + AF_LatinBlue top_blue, + AF_LatinBlue bottom_blue ) + { + FT_Pos base_glyph_height; + FT_Pos limit; + + + base_glyph_height = top_blue->shoot.cur - bottom_blue->shoot.cur; + limit = bottom_blue->shoot.cur - base_glyph_height / 7 - 16; + + af_prevent_bottom_blue_alignment( hints, limit ); + } + + + static void + af_touch_contour( AF_GlyphHints hints, + FT_Int contour ) + { + AF_Point first_point = hints->contours[contour]; + AF_Point p = first_point; + + + do + { + p = p->next; + + p->flags |= AF_FLAG_IGNORE; + if ( !( p->flags & AF_FLAG_CONTROL ) ) + p->flags |= AF_FLAG_TOUCH_Y; + + } while ( p != first_point ); + } + + + static void + af_touch_top_contours( AF_GlyphHints hints, + FT_Int limit_contour ) + { + FT_Pos limit = hints->contour_y_minima[limit_contour]; + + FT_Int contour; + + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos min_y = hints->contour_y_minima[contour]; + FT_Pos max_y = hints->contour_y_maxima[contour]; + + + if ( min_y < max_y && + min_y >= limit ) + af_touch_contour( hints, contour ); + } + } + + + static void + af_touch_bottom_contours( AF_GlyphHints hints, + FT_Int limit_contour ) + { + FT_Pos limit = hints->contour_y_minima[limit_contour]; + + FT_Int contour; + + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos min_y = hints->contour_y_minima[contour]; + FT_Pos max_y = hints->contour_y_maxima[contour]; + + + if ( min_y < max_y && + max_y <= limit ) + af_touch_contour( hints, contour ); + } + } + + + /* Stretch tilde vertically, if necessary, and return the height */ + /* difference between the original and the stretched outline. */ + static FT_Pos + af_latin_stretch_top_tilde( AF_GlyphHints hints, + FT_Int tilde_contour ) + { + AF_Point p = hints->contours[tilde_contour]; + AF_Point first_point = p; + + FT_Pos min_y = hints->contour_y_minima[tilde_contour]; + FT_Pos max_y = hints->contour_y_maxima[tilde_contour]; + + FT_Pos min_measurement = FT_LONG_MAX; + FT_Bool measurement_taken = FALSE; + + FT_Pos height; + FT_Pos extremum_threshold; + FT_Pos target_height; + + + if ( min_y == max_y ) + return 0; + + FT_TRACE4(( "af_latin_stretch_top_tilde: min y: %ld, max y: %ld\n", + min_y, max_y )); + + height = SUB_LONG( max_y, min_y ); + extremum_threshold = height / 8; /* Value 8 is heuristic. */ + + /* Find points that are local vertical round extrema, and which */ + /* do not coincide with the vertical extreme values (i.e., we */ + /* search for the 'other' wiggles in the tilde), then measure the */ + /* distance to the vertical extreme values. Try to find the one */ + /* with the smallest distance. */ + /* */ + /* The algorithm only works for tilde shapes that don't deviate */ + /* from the standard shape too much. In particular, the wiggles */ + /* must be round extrema. */ + do + { + p = p->next; + + if ( !( p->flags & AF_FLAG_CONTROL ) && + p->prev->y == p->y && p->next->y == p->y && + p->y != min_y && p->y != max_y && + p->prev->flags & AF_FLAG_CONTROL && + p->next->flags & AF_FLAG_CONTROL ) + { + /* This point could be a candidate. Find the next and previous */ + /* on-curve points, and make sure they are both either above or */ + /* below the point, then make the measurement. */ + AF_Point prev_on = p->prev; + AF_Point next_on = p->next; + + FT_Pos measurement; + + + while ( prev_on->flags & AF_FLAG_CONTROL ) + prev_on = prev_on->prev; + while ( next_on->flags & AF_FLAG_CONTROL ) + next_on = next_on->next; + + if ( next_on->y > p->y && prev_on->y > p->y ) + measurement = p->y - min_y; + else if ( next_on->y < p->y && prev_on->y < p->y ) + measurement = max_y - p->y; + else + continue; + + /* Ignore hits that are too near to a vertical extremum. */ + if ( measurement < extremum_threshold ) + continue; + + if ( !measurement_taken || measurement < min_measurement ) + { + measurement_taken = TRUE; + min_measurement = measurement; + } + } + + } while ( p != first_point ); + + if ( !measurement_taken ) + min_measurement = 0; + + FT_TRACE4(( "af_latin_stretch_top_tilde: min measurement %ld\n", + min_measurement )); + + /* To preserve the stretched shape we prevent that the tilde */ + /* gets auto-hinted; we do this for all contours equal or */ + /* above the vertical minimum of `tilde_contour`. */ + af_touch_top_contours( hints, tilde_contour ); + + /* XXX This is an important element of the algorithm; */ + /* we need a description. */ + target_height = min_measurement + 64; + if ( height >= target_height ) + return 0; + + /* Do the scaling. */ + p = first_point; + do + { + p = p->next; + /* We adjust the height of the diacritic only, which means */ + /* we are never dealing with large numbers and can thus avoid */ + /* `FT_MulFix`. */ + p->y = ( ( p->y - min_y ) * target_height / height ) + min_y; + + } while ( p != first_point ); + + return target_height - height; + } + + + static FT_Pos + af_latin_stretch_bottom_tilde( AF_GlyphHints hints, + FT_Int tilde_contour ) + { + AF_Point p = hints->contours[tilde_contour]; + AF_Point first_point = p; + + FT_Pos min_y = hints->contour_y_minima[tilde_contour]; + FT_Pos max_y = hints->contour_y_maxima[tilde_contour]; + + FT_Pos min_measurement = FT_LONG_MAX; + FT_Bool measurement_taken = FALSE; + + FT_Pos height; + FT_Pos extremum_threshold; + FT_Pos target_height; + + + if ( min_y == max_y ) + return 0; + + FT_TRACE4(( "af_latin_stretch_bottom_tilde: min y: %ld, max y: %ld\n", + min_y, max_y )); + + height = SUB_LONG( max_y, min_y ); + extremum_threshold = height / 8; + + do + { + p = p->next; + + if ( !( p->flags & AF_FLAG_CONTROL ) && + p->prev->y == p->y && p->next->y == p->y && + p->y != min_y && p->y != max_y && + p->prev->flags & AF_FLAG_CONTROL && + p->next->flags & AF_FLAG_CONTROL ) + { + AF_Point prev_on = p->prev; + AF_Point next_on = p->next; + + FT_Pos measurement; + + + while ( prev_on->flags & AF_FLAG_CONTROL ) + prev_on = prev_on->prev; + while ( next_on->flags & AF_FLAG_CONTROL ) + next_on = next_on->next; + + if ( next_on->y > p->y && prev_on->y > p->y ) + measurement = p->y - min_y; + else if ( next_on->y < p->y && prev_on->y < p->y ) + measurement = max_y - p->y; + else + continue; + + if ( measurement < extremum_threshold ) + continue; + + if ( !measurement_taken || measurement < min_measurement ) + { + measurement_taken = TRUE; + min_measurement = measurement; + } + } + + } while ( p != first_point ); + + if ( !measurement_taken ) + min_measurement = 0; + + FT_TRACE4(( "af_latin_stretch_bottom_tilde: min measurement %ld\n", + min_measurement )); + + af_touch_bottom_contours( hints, tilde_contour ); + + target_height = min_measurement + 64; + if ( height >= target_height ) + return 0; + + p = first_point; + do + { + p = p->next; + p->y = ( ( p->y - max_y ) * target_height / height ) + max_y; + + } while ( p != first_point ); + + return target_height - height; + } + + + /* + As part of `af_latin_stretch_top_tilde`, normally all points in the + tilde are marked as touched, so the existing grid fitting will leave the + tilde misaligned with the grid. + + This function moves the tilde contour down to be grid-fitted. We assume + that if moving the tilde down would cause it to touch or overlap another + countour, the vertical adjustment step will fix it. + + Because the vertical adjustment step comes after all other grid-fitting + steps, the top edge of the contour under the tilde is usually aligned + with a horizontal grid line. The vertical gap enforced by the vertical + adjustment is exactly one pixel, so if the top edge of the contour below + the tilde is on a grid line, the resulting tilde contour will also be + grid-aligned. + + But in cases where the gap is already big enough so that the vertical + adjustment does nothing, this function ensures that even without the + intervention of the vertical adjustment step, the tilde will be + grid-aligned. + + Return the vertical alignment amount. + */ + static FT_Pos + af_latin_align_top_tilde( AF_GlyphHints hints, + FT_Int tilde_contour ) + { + AF_Point p = hints->contours[tilde_contour]; + AF_Point first_point = p; + + FT_Pos min_y = p->y; + FT_Pos max_y = p->y; + + FT_Pos min_y_rounded; + FT_Pos delta; + FT_Pos height; + + + /* Find vertical extrema of the (now stretched) tilde contour. */ + do + { + p = p->next; + if ( p->y < min_y ) + min_y = p->y; + if ( p->y > max_y ) + max_y = p->y; + + } while ( p != first_point ); + + /* Align bottom of the tilde to the grid. */ + min_y_rounded = FT_PIX_ROUND( min_y ); + delta = min_y_rounded - min_y; + height = max_y - min_y; + + /* If the tilde is less than 3 pixels tall, snap the center of it */ + /* to the grid instead of the bottom to improve readability. */ + if ( height < 64 * 3 ) + delta += ( FT_PIX_ROUND( height ) - height ) / 2; + + af_move_contour_vertically( first_point, delta ); + + return delta; + } + + + static FT_Pos + af_latin_align_bottom_tilde( AF_GlyphHints hints, + FT_Int tilde_contour ) + { + AF_Point p = hints->contours[tilde_contour]; + AF_Point first_point = p; + + FT_Pos min_y = p->y; + FT_Pos max_y = p->y; + + FT_Pos max_y_rounded; + FT_Pos delta; + FT_Pos height; + + + do + { + p = p->next; + if ( p->y < min_y ) + min_y = p->y; + if ( p->y > max_y ) + max_y = p->y; + + } while ( p != first_point ); + + max_y_rounded = FT_PIX_ROUND( max_y ); + delta = max_y_rounded - max_y; + height = max_y - min_y; + + if ( height < 64 * 3 ) + delta -= ( FT_PIX_ROUND( height ) - height ) / 2; + + af_move_contour_vertically( first_point, delta ); + + return delta; + } + + + /* Return 1 if the given contour overlaps horizontally with the bounding */ + /* box of all other contours combined. This is a helper for function */ + /* `af_glyph_hints_apply_vertical_separation_adjustments`. */ + static FT_Bool + af_check_contour_horizontal_overlap( AF_GlyphHints hints, + FT_Int contour_index ) + { + FT_Pos contour_max_x = FT_LONG_MIN; + FT_Pos contour_min_x = FT_LONG_MAX; + FT_Pos others_max_x = FT_LONG_MIN; + FT_Pos others_min_x = FT_LONG_MAX; + + FT_Int contour; + + FT_Bool horizontal_overlap; + + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + AF_Point first_point = hints->contours[contour]; + AF_Point p = first_point; + + + /* Ignore dimensionless contours (i.e., contours with only one or */ + /* two points). */ + if ( first_point->next->next == first_point ) + continue; + + do + { + p = p->next; + + if ( contour == contour_index ) + { + if ( p->x < contour_min_x ) + contour_min_x = p->x; + if ( p->x > contour_max_x ) + contour_max_x = p->x; + } + else + { + if ( p->x < others_min_x ) + others_min_x = p->x; + if ( p->x > others_max_x ) + others_max_x = p->x; + } + } while ( p != first_point ); + } + + horizontal_overlap = + ( others_min_x <= contour_max_x && contour_max_x <= others_max_x ) || + ( others_min_x <= contour_min_x && contour_min_x <= others_max_x ) || + ( contour_max_x >= others_max_x && contour_min_x <= others_min_x ); + + return horizontal_overlap; + } + + + static void + af_glyph_hints_apply_vertical_separation_adjustments( + AF_GlyphHints hints, + AF_Dimension dim, + FT_UInt glyph_index, + FT_Pos accent_height_limit, + FT_Hash reverse_charmap ) + { + FT_Bool adjust_top = FALSE; + FT_Bool adjust_below_top = FALSE; + + FT_Bool adjust_bottom = FALSE; + FT_Bool adjust_above_bottom = FALSE; + + size_t* val; + FT_UInt32 adj_type = AF_ADJUST_NONE; + + + FT_TRACE4(( "Entering" + " af_glyph_hints_apply_vertical_separation_adjustments\n" )); + + if ( dim != AF_DIMENSION_VERT ) + return; + + val = ft_hash_num_lookup( (FT_Int)glyph_index, reverse_charmap ); + if ( val ) + { + FT_UInt codepoint = *val; + + + adj_type = af_adjustment_database_lookup( codepoint ); + + if ( adj_type ) + { + adjust_top = !!( adj_type & AF_ADJUST_UP ); + adjust_below_top = !!( adj_type & AF_ADJUST_UP2 ); + + adjust_bottom = !!( adj_type & AF_ADJUST_DOWN ); + adjust_above_bottom = !!( adj_type & AF_ADJUST_DOWN2 ); + } + } + + if ( ( ( adjust_top || adjust_bottom ) && + hints->num_contours >= 2 ) || + ( ( adjust_below_top || adjust_above_bottom ) && + hints->num_contours >= 3 ) ) + { + /* Recompute vertical extrema, this time acting on already */ + /* auto-hinted outlines. */ + af_compute_vertical_extrema( hints ); + } + + if ( ( adjust_top && hints->num_contours >= 2 ) || + ( adjust_below_top && hints->num_contours >= 3 ) ) + { + FT_Int high_contour; + FT_Pos high_min_y; + FT_Pos high_max_y; + FT_Pos high_height; + + FT_Int tilde_contour; + FT_Pos tilde_min_y; + FT_Pos tilde_max_y; + FT_Pos tilde_height; + + FT_Int contour; + FT_Bool horizontal_overlap; + + FT_Pos min_distance = 64; + FT_Pos adjustment_amount; + FT_Pos calculated_amount; + FT_Pos centering_adjustment = 0; + FT_Pos pos; + + FT_Bool is_top_tilde = !!( adj_type & AF_ADJUST_TILDE_TOP ); + FT_Bool is_below_top_tilde = !!( adj_type & AF_ADJUST_TILDE_TOP2 ); + + + FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n" + " Applying vertical adjustment: %s\n", + adjust_top ? "AF_ADJUST_TOP" : "AF_ADJUST_TOP2" )); + + high_contour = adjust_below_top + ? af_find_second_highest_contour( hints ) + : af_find_highest_contour( hints ); + + /* Check for a horizontal overlap between the high contour and the */ + /* rest. If there is no overlap, do not adjust. */ + horizontal_overlap = + af_check_contour_horizontal_overlap( hints, high_contour ); + if ( !horizontal_overlap ) + { + FT_TRACE4(( " High contour does not horizontally overlap" + " with other contours.\n" + " Skipping adjustment.\n" )); + return; + } + + high_min_y = hints->contour_y_minima[high_contour]; + high_max_y = hints->contour_y_maxima[high_contour]; + high_height = high_max_y - high_min_y; + + if ( high_height > accent_height_limit ) + { + FT_TRACE4(( " High contour height (%.2f) exceeds accent height" + " limit (%.2f).\n" + " Skipping adjustment.\n", + (double)high_height / 64, + (double)accent_height_limit / 64 )); + return; + } + + /* If the difference between the vertical minimum of the high */ + /* contour and the vertical maximum of another contour is less */ + /* than a pixel, shift up the high contour to make the distance */ + /* one pixel. */ + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos min_y; + FT_Pos max_y; + FT_Pos distance; + + + if ( contour == high_contour ) + continue; + + min_y = hints->contour_y_minima[contour]; + max_y = hints->contour_y_maxima[contour]; + + /* We also check that the y minimum of the 'other' contour */ + /* is below the high contour to avoid potential false hits */ + /* with contours enclosed in the high one. */ + distance = high_min_y - max_y; + if ( distance < 64 && + distance < min_distance && + min_y < high_min_y ) + min_distance = distance; + } + + adjustment_amount = 64 - min_distance; + + if ( is_top_tilde || is_below_top_tilde ) + { + tilde_contour = adjust_top + ? high_contour + : ( is_below_top_tilde + ? high_contour + : af_find_highest_contour( hints ) ); + + tilde_min_y = hints->contour_y_minima[tilde_contour]; + tilde_max_y = hints->contour_y_maxima[tilde_contour]; + tilde_height = tilde_max_y - tilde_min_y; + + /* The vertical separation adjustment potentially undoes a */ + /* tilde center alignment. If it would grid-align a tilde */ + /* less than 3 pixels in height, shift additionally to */ + /* re-center the tilde. */ + + pos = high_min_y + adjustment_amount; + if ( adjust_below_top && is_top_tilde ) + pos += high_height; + + if ( pos % 64 == 0 && tilde_height < 3 * 64 ) + { + centering_adjustment = ( FT_PIX_ROUND( tilde_height ) - + tilde_height ) / 2; + + FT_TRACE4(( " Additional tilde centering adjustment: %ld\n", + centering_adjustment )); + } + } + + if ( ( adjust_top && is_top_tilde ) || + ( adjust_below_top && is_below_top_tilde ) ) + calculated_amount = adjustment_amount + centering_adjustment; + else + calculated_amount = adjustment_amount; + + /* allow a delta of 2/64px to handle rounding differences */ + FT_TRACE4(( " Calculated adjustment amount: %ld%s\n", + calculated_amount, + ( calculated_amount < -2 || + ( adjustment_amount > 66 && calculated_amount > 66 ) ) + ? " (out of range [-2;66], not adjusting)" : "" )); + + if ( calculated_amount != 0 && + calculated_amount >= -2 && + ( calculated_amount <= 66 || adjustment_amount <= 66 ) ) + { + /* Value 8 is heuristic. */ + FT_Pos height_delta = high_height / 8; + FT_Pos min_y_limit = high_min_y - height_delta; + + + FT_TRACE4(( " Pushing high contour %ld units up\n", + calculated_amount )); + + /* While we use only a single contour (the 'high' one) for */ + /* computing `adjustment_amount`, we apply it to all contours */ + /* that are (approximately) in the same vertical range or */ + /* higher. This covers, for example, the inner contour of */ + /* the Czech ring accent or the second acute accent in the */ + /* Hungarian double acute accent. */ + af_move_contours_up( hints, min_y_limit, adjustment_amount ); + + if ( adjust_below_top && is_top_tilde ) + { + FT_TRACE4(( " Pushing top tilde %ld units up\n", + centering_adjustment )); + + af_move_contours_up( hints, + min_y_limit + high_height, + centering_adjustment ); + } + } + } + + if ( ( adjust_bottom && hints->num_contours >= 2 ) || + ( adjust_above_bottom && hints->num_contours >= 3 ) ) + { + FT_Int low_contour; + FT_Pos low_min_y; + FT_Pos low_max_y; + FT_Pos low_height; + + FT_Int tilde_contour; + FT_Pos tilde_min_y; + FT_Pos tilde_max_y; + FT_Pos tilde_height; + + FT_Int contour; + FT_Bool horizontal_overlap; + + FT_Pos min_distance = 64; + FT_Pos adjustment_amount; + FT_Pos calculated_amount; + FT_Pos centering_adjustment = 0; + FT_Pos pos; + + FT_Bool is_bottom_tilde = + !!( adj_type & AF_ADJUST_TILDE_BOTTOM ); + FT_Bool is_above_bottom_tilde = + !!( adj_type & AF_ADJUST_TILDE_BOTTOM2 ); + + + FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n" + " Applying vertical adjustment: %s\n", + adjust_bottom ? "AF_ADJUST_DOWN": "AF_ADJUST_DOWN2" )); + + low_contour = adjust_above_bottom + ? af_find_second_lowest_contour( hints ) + : af_find_lowest_contour( hints ); + + horizontal_overlap = + af_check_contour_horizontal_overlap( hints, low_contour ); + if ( !horizontal_overlap ) + { + FT_TRACE4(( " Low contour does not horizontally overlap" + " with other contours.\n" + " Skipping adjustment.\n" )); + return; + } + + low_min_y = hints->contour_y_minima[low_contour]; + low_max_y = hints->contour_y_maxima[low_contour]; + low_height = low_max_y - low_min_y; + + if ( low_height > accent_height_limit ) + { + FT_TRACE4(( " Low contour height (%.2f) exceeds accent height" + " limit (%.2f).\n" + " Skipping adjustment.\n", + (double)low_height / 64, + (double)accent_height_limit / 64 )); + return; + } + + for ( contour = 0; contour < hints->num_contours; contour++ ) + { + FT_Pos min_y; + FT_Pos max_y; + FT_Pos distance; + + + if ( contour == low_contour ) + continue; + + min_y = hints->contour_y_minima[contour]; + max_y = hints->contour_y_maxima[contour]; + + distance = min_y - low_max_y; + if ( distance < 64 && + distance < min_distance && + max_y > low_max_y ) + min_distance = distance; + } + + adjustment_amount = 64 - min_distance; + + if ( is_bottom_tilde || is_above_bottom_tilde ) + { + tilde_contour = adjust_bottom + ? low_contour + : ( is_above_bottom_tilde + ? low_contour + : af_find_lowest_contour( hints ) ); + + tilde_min_y = hints->contour_y_minima[tilde_contour]; + tilde_max_y = hints->contour_y_maxima[tilde_contour]; + tilde_height = tilde_max_y - tilde_min_y; + + pos = low_max_y - adjustment_amount; + if ( adjust_above_bottom && is_bottom_tilde ) + pos -= low_height; + + if ( pos % 64 == 0 && tilde_height < 3 * 64 ) + { + centering_adjustment = ( FT_PIX_ROUND( tilde_height ) - + tilde_height ) / 2; + + FT_TRACE4(( " Additional tilde centering adjustment: %ld\n", + centering_adjustment )); + } + } + + if ( ( adjust_bottom && is_bottom_tilde ) || + ( adjust_above_bottom && is_above_bottom_tilde ) ) + calculated_amount = adjustment_amount + centering_adjustment; + else + calculated_amount = adjustment_amount; + + FT_TRACE4(( " Calculated adjustment amount: %ld%s\n", + calculated_amount, + ( calculated_amount < -2 || + ( adjustment_amount > 66 && calculated_amount > 66 ) ) + ? " (out of range [-2;66], not adjusting)" : "" )); + + if ( calculated_amount != 0 && + calculated_amount >= -2 && + ( calculated_amount <= 66 || adjustment_amount <= 66 ) ) + { + FT_Pos height_delta = low_height / 8; + FT_Pos max_y_limit = low_max_y + height_delta; + + + FT_TRACE4(( " Pushing low contour %ld units down\n", + calculated_amount )); + + af_move_contours_down( hints, max_y_limit, adjustment_amount ); + + if ( adjust_above_bottom && is_bottom_tilde ) + { + FT_TRACE4(( " Pushing bottom tilde %ld units down\n", + centering_adjustment )); + + af_move_contours_down( hints, + max_y_limit - low_height, + centering_adjustment ); + } + } + } + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( !( ( ( adjust_top || adjust_bottom ) && + hints->num_contours >= 2 ) || + ( ( adjust_below_top || adjust_above_bottom ) && + hints->num_contours >= 3 ) ) ) + FT_TRACE4(( "af_glyph_hints_apply_vertical_separation_adjustments:\n" + " No vertical adjustment applied\n" )); +#endif + + FT_TRACE4(( "Exiting" + " af_glyph_hints_apply_vertical_separation_adjustments\n" )); + } + + +#undef FT_COMPONENT +#define FT_COMPONENT aflatin + + /* Compute the snapped width of a given stem, ignoring very thin ones. */ /* There is a lot of voodoo in this function; changing the hard-coded */ /* parameters influence the whole hinting process. */ @@ -2998,13 +4214,15 @@ af_latin_hint_edges( AF_GlyphHints hints, AF_Dimension dim ) { - AF_AxisHints axis = &hints->axis[dim]; - AF_Edge edges = axis->edges; - AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); - FT_PtrDist n_edges; - AF_Edge edge; - AF_Edge anchor = NULL; - FT_Int has_serifs = 0; + AF_AxisHints axis = &hints->axis[dim]; + + AF_Edge edges = axis->edges; + AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges ); + AF_Edge edge; + FT_PtrDist n_edges; + + AF_Edge anchor = NULL; + FT_Bool has_non_stem_edges = 0; AF_StyleClass style_class = hints->metrics->style_class; AF_ScriptClass script_class = af_script_classes[style_class->script]; @@ -3131,7 +4349,7 @@ edge2 = edge->link; if ( !edge2 ) { - has_serifs++; + has_non_stem_edges = TRUE; continue; } @@ -3408,7 +4626,7 @@ } } - if ( has_serifs || !anchor ) + if ( has_non_stem_edges || !anchor ) { /* * now hint the remaining edges (serifs and single) in order @@ -3426,9 +4644,75 @@ if ( edge->serif ) { + AF_Edge e, top, bottom; + FT_Pos min_pos, max_pos; + + + /* Check whether we have a real serif -- if there are */ + /* other edges with overlapping (or enclosed) segments */ + /* between the primary and serif edge, we have not. */ + /* */ + /* Such a situation might happen if an accent is very */ + /* near to its base glyph (for example, Vietnamese */ + /* uppercase letters with two accents in `arial.ttf`), */ + /* and the segment detection algorithm classifies the */ + /* top of the accent incorrectly as a serif. */ delta = edge->serif->opos - edge->opos; if ( delta < 0 ) + { delta = -delta; + + top = edge; + bottom = edge->serif; + } + else + { + top = edge->serif; + bottom = edge; + } + + if ( delta < 64 + 32 ) + { + /* take care of outline orientation while computing extrema */ + min_pos = FT_MIN( FT_MIN( FT_MIN( top->first->first->v, + top->first->last->v ), + FT_MIN( top->last->first->v, + top->last->last->v ) ), + FT_MIN( FT_MIN( bottom->first->first->v, + bottom->first->last->v ), + FT_MIN( bottom->last->first->v, + bottom->last->last->v ) ) ); + max_pos = FT_MAX( FT_MAX( FT_MAX( top->first->first->v, + top->first->last->v ), + FT_MAX( top->last->first->v, + top->last->last->v ) ), + FT_MAX( FT_MAX( bottom->first->first->v, + bottom->first->last->v ), + FT_MAX( bottom->last->first->v, + bottom->last->last->v ) ) ); + + for ( e = bottom + 1; e < top; e++ ) + { + FT_Pos e_min = FT_MIN( FT_MIN( e->first->first->v, + e->first->last->v ), + FT_MIN( e->last->first->v, + e->last->last->v ) ); + FT_Pos e_max = FT_MAX( FT_MAX( e->first->first->v, + e->first->last->v ), + FT_MAX( e->last->first->v, + e->last->last->v ) ); + + if ( !( ( e_min < min_pos && e_max < min_pos ) || + ( e_min > max_pos && e_max > max_pos ) ) ) + { + delta = 1000; /* not a real serif */ + break; + } + } + + if ( delta == 1000 ) + continue; + } } if ( delta < 64 + 16 ) @@ -3562,6 +4846,8 @@ AF_LatinAxis axis; + FT_Pos accent_height_limit = 0; + error = af_glyph_hints_reload( hints, outline ); if ( error ) @@ -3581,11 +4867,172 @@ if ( AF_HINTS_DO_VERTICAL( hints ) ) { + size_t* val; + + FT_Int top_tilde_contour = 0; + FT_Int bottom_tilde_contour = 0; + + FT_Int below_top_tilde_contour = 0; + FT_Int above_bottom_tilde_contour = 0; + + AF_LatinBlue capital_top_blue = NULL; + AF_LatinBlue capital_bottom_blue = NULL; + + AF_LatinBlue small_top_blue = NULL; + AF_LatinBlue small_bottom_blue = NULL; + + FT_Bool have_flags = FALSE; + + FT_Bool is_top_tilde = FALSE; + FT_Bool is_bottom_tilde = FALSE; + + FT_Bool is_below_top_tilde = FALSE; + FT_Bool is_above_bottom_tilde = FALSE; + + FT_Bool ignore_capital_top = FALSE; + FT_Bool ignore_capital_bottom = FALSE; + + FT_Bool ignore_small_top = FALSE; + FT_Bool ignore_small_bottom = FALSE; + + FT_Bool do_height_check = TRUE; + + FT_Pos limit; + FT_Pos y_offset; + + + val = ft_hash_num_lookup( (FT_Int)glyph_index, + metrics->root.reverse_charmap ); + if ( val ) + { + FT_UInt codepoint = *val; + FT_UInt32 adj_type = af_adjustment_database_lookup( codepoint ); + + + if ( adj_type ) + { + have_flags = !!adj_type; + + is_top_tilde = !!( adj_type & AF_ADJUST_TILDE_TOP ); + is_bottom_tilde = !!( adj_type & AF_ADJUST_TILDE_BOTTOM ); + + is_below_top_tilde = !!( adj_type & AF_ADJUST_TILDE_TOP2 ); + is_above_bottom_tilde = !!( adj_type & AF_ADJUST_TILDE_BOTTOM2 ); + + ignore_capital_top = !!( adj_type & AF_IGNORE_CAPITAL_TOP ); + ignore_capital_bottom = !!( adj_type & AF_IGNORE_CAPITAL_BOTTOM ); + + ignore_small_top = !!( adj_type & AF_IGNORE_SMALL_TOP ); + ignore_small_bottom = !!( adj_type & AF_IGNORE_SMALL_BOTTOM ); + + do_height_check = !( adj_type & AF_ADJUST_NO_HEIGHT_CHECK ); + } + } + + if ( is_top_tilde || is_bottom_tilde || + is_below_top_tilde || is_above_bottom_tilde ) + af_compute_vertical_extrema( hints ); + + /* Process inner tilde glyphs first. */ + if ( is_below_top_tilde ) + { + below_top_tilde_contour = af_find_second_highest_contour( hints ); + + y_offset = af_latin_stretch_top_tilde( + hints, below_top_tilde_contour ); + y_offset += af_latin_align_top_tilde( + hints, below_top_tilde_contour ); + + limit = hints->contour_y_minima[below_top_tilde_contour]; + af_move_contours_up( hints, limit, y_offset ); + } + if ( is_above_bottom_tilde ) + { + above_bottom_tilde_contour = af_find_second_lowest_contour( hints ); + + y_offset = af_latin_stretch_bottom_tilde( + hints, above_bottom_tilde_contour ); + y_offset -= af_latin_align_bottom_tilde( + hints, above_bottom_tilde_contour ); + + limit = hints->contour_y_maxima[above_bottom_tilde_contour]; + af_move_contours_down( hints, limit, y_offset ); + } + + if ( is_top_tilde ) + { + top_tilde_contour = af_find_highest_contour( hints ); + + (void)af_latin_stretch_top_tilde( hints, top_tilde_contour ); + (void)af_latin_align_top_tilde( hints, top_tilde_contour ); + } + if ( is_bottom_tilde ) + { + bottom_tilde_contour = af_find_lowest_contour( hints ); + + (void)af_latin_stretch_bottom_tilde( hints, bottom_tilde_contour ); + (void)af_latin_align_bottom_tilde( hints, bottom_tilde_contour ); + } + axis = &metrics->axis[AF_DIMENSION_VERT]; error = af_latin_hints_detect_features( hints, axis->width_count, axis->widths, AF_DIMENSION_VERT ); + + if ( have_flags ) + { + af_latin_get_base_glyph_blues( hints, + TRUE, + &capital_top_blue, + &capital_bottom_blue ); + af_latin_get_base_glyph_blues( hints, + FALSE, + &small_top_blue, + &small_bottom_blue ); + + if ( do_height_check ) + { + /* Set a heuristic limit for the accent height so that */ + /* `af_glyph_hints_apply_vertical_separation_adjustments` */ + /* can correctly ignore the case where an accent is */ + /* unexpectedly not the highest (or lowest) contour. */ + + /* Either 2/3 of the lowercase blue zone height... */ + if ( small_top_blue && small_bottom_blue ) + accent_height_limit = 2 * ( small_top_blue->shoot.cur - + small_bottom_blue->shoot.cur ) / 3; + /* or 1/2 of the uppercase blue zone height... */ + else if ( capital_top_blue && capital_bottom_blue ) + accent_height_limit = ( capital_top_blue->shoot.cur - + capital_bottom_blue->shoot.cur ) / 2; + /* or half of the standard PostScript ascender value (8/10) */ + /* of the EM value, scaled. */ + else + accent_height_limit = FT_MulFix( metrics->units_per_em * 4 / 10, + metrics->root.scaler.y_scale ); + } + } + + if ( capital_top_blue && capital_bottom_blue ) + { + if ( ignore_capital_top ) + af_latin_ignore_top( hints, + capital_top_blue, capital_bottom_blue ); + if ( ignore_capital_bottom ) + af_latin_ignore_bottom( hints, + capital_top_blue, capital_bottom_blue ); + } + if ( small_top_blue && small_bottom_blue ) + { + if ( ignore_small_top ) + af_latin_ignore_top( hints, + small_top_blue, small_bottom_blue ); + if ( ignore_small_bottom ) + af_latin_ignore_bottom( hints, + small_top_blue, small_bottom_blue ); + } + if ( error ) goto Exit; @@ -3604,6 +5051,12 @@ af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim ); af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); + af_glyph_hints_apply_vertical_separation_adjustments( + hints, + (AF_Dimension)dim, + glyph_index, + accent_height_limit, + metrics->root.reverse_charmap ); } } @@ -3632,7 +5085,7 @@ (AF_WritingSystem_InitMetricsFunc) af_latin_metrics_init, /* style_metrics_init */ (AF_WritingSystem_ScaleMetricsFunc)af_latin_metrics_scale, /* style_metrics_scale */ - (AF_WritingSystem_DoneMetricsFunc) NULL, /* style_metrics_done */ + (AF_WritingSystem_DoneMetricsFunc) af_latin_metrics_done, /* style_metrics_done */ (AF_WritingSystem_GetStdWidthsFunc)af_latin_get_standard_widths, /* style_metrics_getstdw */ (AF_WritingSystem_InitHintsFunc) af_latin_hints_init, /* style_hints_init */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h index 54e50615021..82b4b0d480d 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h @@ -5,7 +5,7 @@ * Auto-fitter hinting routines for latin writing system * (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -61,17 +61,26 @@ FT_BEGIN_HEADER ( (b)->properties & AF_BLUE_PROPERTY_LATIN_X_HEIGHT ) #define AF_LATIN_IS_LONG_BLUE( b ) \ ( (b)->properties & AF_BLUE_PROPERTY_LATIN_LONG ) +#define AF_LATIN_IS_CAPITAL_BOTTOM_BLUE( b ) \ + ( (b)->properties & AF_BLUE_PROPERTY_LATIN_CAPITAL_BOTTOM ) +#define AF_LATIN_IS_SMALL_BOTTOM_BLUE( b ) \ + ( (b)->properties & AF_BLUE_PROPERTY_LATIN_SMALL_BOTTOM ) #define AF_LATIN_MAX_WIDTHS 16 -#define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */ -#define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */ -#define AF_LATIN_BLUE_SUB_TOP ( 1U << 2 ) /* we have a subscript top */ - /* blue zone */ -#define AF_LATIN_BLUE_NEUTRAL ( 1U << 3 ) /* we have neutral blue zone */ -#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 4 ) /* used for scale adjustment */ - /* optimization */ +#define AF_LATIN_BLUE_ACTIVE ( 1U << 0 ) /* zone height is <= 3/4px */ +#define AF_LATIN_BLUE_TOP ( 1U << 1 ) /* we have a top blue zone */ +#define AF_LATIN_BLUE_SUB_TOP ( 1U << 2 ) /* we have a subscript */ + /* top blue zone */ +#define AF_LATIN_BLUE_NEUTRAL ( 1U << 3 ) /* we have a neutral blue */ + /* zone */ +#define AF_LATIN_BLUE_ADJUSTMENT ( 1U << 4 ) /* used for scale adjustm. */ + /* optimization */ +#define AF_LATIN_BLUE_BOTTOM ( 1U << 5 ) /* we have a capital */ + /* letter bottom blue zone */ +#define AF_LATIN_BLUE_BOTTOM_SMALL ( 1U << 6 ) /* we have a small letter */ + /* bottom blue zone */ typedef struct AF_LatinBlueRec_ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c index af1d59a6896..d84adc09679 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (body). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h index 99f0e15f92b..a04b4df0b3b 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h @@ -4,7 +4,7 @@ * * Auto-fitter glyph loading routines (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c index 726f6ca2b78..22d85a889e8 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (body). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -146,7 +146,7 @@ if ( !af_style_classes[ss] ) { - FT_TRACE2(( "af_property_set: Invalid value %d for property `%s'\n", + FT_TRACE2(( "af_property_set: Invalid value %u for property `%s'\n", *fallback_script, property_name )); return FT_THROW( Invalid_Argument ); } @@ -412,6 +412,11 @@ module->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; module->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; +#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \ + defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC ) + ft_hb_funcs_init( module ); +#endif + return FT_Err_Ok; } @@ -421,6 +426,11 @@ { FT_UNUSED( ft_module ); +#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \ + defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC ) + ft_hb_funcs_done( (AF_Module)ft_module ); +#endif + #ifdef FT_DEBUG_AUTOFIT if ( af_debug_hints_rec_->memory ) af_glyph_hints_done( af_debug_hints_rec_ ); diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h index 91a1abfef1f..c62421ef696 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h @@ -4,7 +4,7 @@ * * Auto-fitter module implementation (specification). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -22,6 +22,7 @@ #include #include +#include "ft-hb.h" FT_BEGIN_HEADER @@ -40,6 +41,11 @@ FT_BEGIN_HEADER FT_Bool no_stem_darkening; FT_Int darken_params[8]; +#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \ + defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC ) + ft_hb_funcs_t* hb_funcs; +#endif + } AF_ModuleRec, *AF_Module; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c index 007b4328189..fd54948f3a5 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (body). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -73,9 +73,11 @@ { AF_UNIRANGE_REC( 0x0600, 0x06FF ), /* Arabic */ AF_UNIRANGE_REC( 0x0750, 0x07FF ), /* Arabic Supplement */ + AF_UNIRANGE_REC( 0x0870, 0x089F ), /* Arabic Extended-B */ AF_UNIRANGE_REC( 0x08A0, 0x08FF ), /* Arabic Extended-A */ AF_UNIRANGE_REC( 0xFB50, 0xFDFF ), /* Arabic Presentation Forms-A */ AF_UNIRANGE_REC( 0xFE70, 0xFEFF ), /* Arabic Presentation Forms-B */ + AF_UNIRANGE_REC( 0x10EC0, 0x10EFF ), /* Arabic Extended-C */ AF_UNIRANGE_REC( 0x1EE00, 0x1EEFF ), /* Arabic Mathematical Alphabetic Symbols */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -90,8 +92,9 @@ AF_UNIRANGE_REC( 0x06DF, 0x06E4 ), AF_UNIRANGE_REC( 0x06E7, 0x06E8 ), AF_UNIRANGE_REC( 0x06EA, 0x06ED ), - AF_UNIRANGE_REC( 0x08D4, 0x08E1 ), - AF_UNIRANGE_REC( 0x08D3, 0x08FF ), + AF_UNIRANGE_REC( 0x0897, 0x089F ), + AF_UNIRANGE_REC( 0x08CA, 0x08E1 ), + AF_UNIRANGE_REC( 0x08E3, 0x08FF ), AF_UNIRANGE_REC( 0xFBB2, 0xFBC1 ), AF_UNIRANGE_REC( 0xFE70, 0xFE70 ), AF_UNIRANGE_REC( 0xFE72, 0xFE72 ), @@ -101,6 +104,7 @@ AF_UNIRANGE_REC( 0xFE7A, 0xFE7A ), AF_UNIRANGE_REC( 0xFE7C, 0xFE7C ), AF_UNIRANGE_REC( 0xFE7E, 0xFE7E ), + AF_UNIRANGE_REC( 0x10EFD, 0x10EFF ), AF_UNIRANGE_REC( 0, 0 ) }; @@ -198,8 +202,9 @@ const AF_Script_UniRangeRec af_cans_uniranges[] = { - AF_UNIRANGE_REC( 0x1400, 0x167F ), /* Unified Canadian Aboriginal Syllabics */ - AF_UNIRANGE_REC( 0x18B0, 0x18FF ), /* Unified Canadian Aboriginal Syllabics Extended */ + AF_UNIRANGE_REC( 0x1400, 0x167F ), /* Unified Canadian Aboriginal Syllabics */ + AF_UNIRANGE_REC( 0x18B0, 0x18FF ), /* Unified Canadian Aboriginal Syllabics Extended */ + AF_UNIRANGE_REC( 0x11AB0, 0x11ABF ), /* Unified Canadian Aboriginal Syllabics Extended-A */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -259,6 +264,9 @@ }; + /* TODO: Split off data for new 'cyrb' (subscript) and 'cyrp' */ + /* (superscript) groups (mainly from the Extended-D block), */ + /* in analogy to 'latb' and 'latp'? */ const AF_Script_UniRangeRec af_cyrl_uniranges[] = { AF_UNIRANGE_REC( 0x0400, 0x04FF ), /* Cyrillic */ @@ -266,6 +274,7 @@ AF_UNIRANGE_REC( 0x2DE0, 0x2DFF ), /* Cyrillic Extended-A */ AF_UNIRANGE_REC( 0xA640, 0xA69F ), /* Cyrillic Extended-B */ AF_UNIRANGE_REC( 0x1C80, 0x1C8F ), /* Cyrillic Extended-C */ + AF_UNIRANGE_REC( 0x1E030, 0x1E08F ), /* Cyrillic Extended-D */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -285,15 +294,16 @@ const AF_Script_UniRangeRec af_deva_uniranges[] = { - AF_UNIRANGE_REC( 0x0900, 0x093B ), /* Devanagari */ + AF_UNIRANGE_REC( 0x0900, 0x093B ), /* Devanagari */ /* omitting U+093C nukta */ - AF_UNIRANGE_REC( 0x093D, 0x0950 ), /* ... continued */ + AF_UNIRANGE_REC( 0x093D, 0x0950 ), /* ... continued */ /* omitting U+0951 udatta, U+0952 anudatta */ - AF_UNIRANGE_REC( 0x0953, 0x0963 ), /* ... continued */ + AF_UNIRANGE_REC( 0x0953, 0x0963 ), /* ... continued */ /* omitting U+0964 danda, U+0965 double danda */ - AF_UNIRANGE_REC( 0x0966, 0x097F ), /* ... continued */ - AF_UNIRANGE_REC( 0x20B9, 0x20B9 ), /* (new) Rupee sign */ - AF_UNIRANGE_REC( 0xA8E0, 0xA8FF ), /* Devanagari Extended */ + AF_UNIRANGE_REC( 0x0966, 0x097F ), /* ... continued */ + AF_UNIRANGE_REC( 0x20B9, 0x20B9 ), /* (new) Rupee sign */ + AF_UNIRANGE_REC( 0xA8E0, 0xA8FF ), /* Devanagari Extended */ + AF_UNIRANGE_REC( 0x11B00, 0x11B5F ), /* Devanagari Extended-A */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -329,6 +339,7 @@ AF_UNIRANGE_REC( 0x1380, 0x139F ), /* Ethiopic Supplement */ AF_UNIRANGE_REC( 0x2D80, 0x2DDF ), /* Ethiopic Extended */ AF_UNIRANGE_REC( 0xAB00, 0xAB2F ), /* Ethiopic Extended-A */ + AF_UNIRANGE_REC( 0x1E7E0, 0x1E7FF ), /* Ethiopic Extended-B */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -534,7 +545,7 @@ { AF_UNIRANGE_REC( 0x0EB1, 0x0EB1 ), AF_UNIRANGE_REC( 0x0EB4, 0x0EBC ), - AF_UNIRANGE_REC( 0x0EC8, 0x0ECD ), + AF_UNIRANGE_REC( 0x0EC8, 0x0ECE ), AF_UNIRANGE_REC( 0, 0 ) }; @@ -567,12 +578,15 @@ AF_UNIRANGE_REC( 0x2C7E, 0x2C7F ), /* ... continued */ AF_UNIRANGE_REC( 0x2E00, 0x2E7F ), /* Supplemental Punctuation */ AF_UNIRANGE_REC( 0xA720, 0xA76F ), /* Latin Extended-D */ - AF_UNIRANGE_REC( 0xA771, 0xA7F7 ), /* ... continued */ + AF_UNIRANGE_REC( 0xA771, 0xA7F0 ), /* ... continued */ + AF_UNIRANGE_REC( 0xA7F2, 0xA7F7 ), /* ... continued */ AF_UNIRANGE_REC( 0xA7FA, 0xA7FF ), /* ... continued */ AF_UNIRANGE_REC( 0xAB30, 0xAB5B ), /* Latin Extended-E */ - AF_UNIRANGE_REC( 0xAB60, 0xAB6F ), /* ... continued */ + AF_UNIRANGE_REC( 0xAB60, 0xAB68 ), /* ... continued */ + AF_UNIRANGE_REC( 0xAB6A, 0xAB6F ), /* ... continued */ AF_UNIRANGE_REC( 0xFB00, 0xFB06 ), /* Alphab. Present. Forms (Latin Ligs) */ AF_UNIRANGE_REC( 0x1D400, 0x1D7FF ), /* Mathematical Alphanumeric Symbols */ + AF_UNIRANGE_REC( 0x1DF00, 0x1DFFF ), /* Latin Extended-G */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -588,7 +602,7 @@ AF_UNIRANGE_REC( 0x02B9, 0x02DF ), AF_UNIRANGE_REC( 0x02E5, 0x02FF ), AF_UNIRANGE_REC( 0x0300, 0x036F ), - AF_UNIRANGE_REC( 0x1AB0, 0x1ABE ), + AF_UNIRANGE_REC( 0x1AB0, 0x1AEB ), AF_UNIRANGE_REC( 0x1DC0, 0x1DFF ), AF_UNIRANGE_REC( 0x2017, 0x2017 ), AF_UNIRANGE_REC( 0x203E, 0x203E ), @@ -625,8 +639,11 @@ AF_UNIRANGE_REC( 0x2070, 0x207F ), /* superscript digits and letters */ AF_UNIRANGE_REC( 0x2C7D, 0x2C7D ), /* modifier letter capital v */ AF_UNIRANGE_REC( 0xA770, 0xA770 ), /* modifier letter us */ + AF_UNIRANGE_REC( 0xA7F1, 0xA7F1 ), /* modifier letter capital s */ AF_UNIRANGE_REC( 0xA7F8, 0xA7F9 ), /* more modifier letters */ AF_UNIRANGE_REC( 0xAB5C, 0xAB5F ), /* more modifier letters */ + AF_UNIRANGE_REC( 0xAB69, 0xAB69 ), /* modifier letter small turned w */ + AF_UNIRANGE_REC( 0x10780, 0x107FB ), /* Latin Extended-F */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -638,7 +655,8 @@ const AF_Script_UniRangeRec af_lisu_uniranges[] = { - AF_UNIRANGE_REC( 0xA4D0, 0xA4FF ), /* Lisu */ + AF_UNIRANGE_REC( 0xA4D0, 0xA4FF ), /* Lisu */ + AF_UNIRANGE_REC( 0x11FB0, 0x11FBF ), /* Lisu Supplement */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -696,6 +714,7 @@ AF_UNIRANGE_REC( 0x1000, 0x109F ), /* Myanmar */ AF_UNIRANGE_REC( 0xA9E0, 0xA9FF ), /* Myanmar Extended-B */ AF_UNIRANGE_REC( 0xAA60, 0xAA7F ), /* Myanmar Extended-A */ + AF_UNIRANGE_REC( 0x116D0, 0x116FF ), /* Myanmar Extended-C */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -836,6 +855,7 @@ const AF_Script_UniRangeRec af_sinh_nonbase_uniranges[] = { + AF_UNIRANGE_REC( 0x0D81, 0x0D81 ), AF_UNIRANGE_REC( 0x0DCA, 0x0DCA ), AF_UNIRANGE_REC( 0x0DD2, 0x0DD6 ), AF_UNIRANGE_REC( 0, 0 ) @@ -859,7 +879,8 @@ const AF_Script_UniRangeRec af_taml_uniranges[] = { - AF_UNIRANGE_REC( 0x0B80, 0x0BFF ), /* Tamil */ + AF_UNIRANGE_REC( 0x0B80, 0x0BFF ), /* Tamil */ + AF_UNIRANGE_REC( 0x11FC0, 0x11FFF ), /* Tamil Supplement */ AF_UNIRANGE_REC( 0, 0 ) }; @@ -899,6 +920,7 @@ { AF_UNIRANGE_REC( 0x0C00, 0x0C00 ), AF_UNIRANGE_REC( 0x0C04, 0x0C04 ), + AF_UNIRANGE_REC( 0x0C3C, 0x0C3C ), AF_UNIRANGE_REC( 0x0C3E, 0x0C40 ), AF_UNIRANGE_REC( 0x0C46, 0x0C56 ), AF_UNIRANGE_REC( 0x0C62, 0x0C63 ), @@ -992,6 +1014,7 @@ AF_UNIRANGE_REC( 0xA806, 0xA806 ), AF_UNIRANGE_REC( 0xA80B, 0xA80B ), AF_UNIRANGE_REC( 0xA825, 0xA826 ), + AF_UNIRANGE_REC( 0xA82C, 0xA82C ), AF_UNIRANGE_REC( 0, 0 ) }; @@ -1048,15 +1071,21 @@ AF_UNIRANGE_REC( 0xFE10, 0xFE1F ), /* Vertical forms */ AF_UNIRANGE_REC( 0xFE30, 0xFE4F ), /* CJK Compatibility Forms */ AF_UNIRANGE_REC( 0xFF00, 0xFFEF ), /* Halfwidth and Fullwidth Forms */ + AF_UNIRANGE_REC( 0x1AFF0, 0x1AFFF ), /* Kana Extended-B */ AF_UNIRANGE_REC( 0x1B000, 0x1B0FF ), /* Kana Supplement */ AF_UNIRANGE_REC( 0x1B100, 0x1B12F ), /* Kana Extended-A */ + AF_UNIRANGE_REC( 0x1B130, 0x1B16F ), /* Small Kana Extension */ AF_UNIRANGE_REC( 0x1D300, 0x1D35F ), /* Tai Xuan Hing Symbols */ AF_UNIRANGE_REC( 0x20000, 0x2A6DF ), /* CJK Unified Ideographs Extension B */ AF_UNIRANGE_REC( 0x2A700, 0x2B73F ), /* CJK Unified Ideographs Extension C */ AF_UNIRANGE_REC( 0x2B740, 0x2B81F ), /* CJK Unified Ideographs Extension D */ AF_UNIRANGE_REC( 0x2B820, 0x2CEAF ), /* CJK Unified Ideographs Extension E */ AF_UNIRANGE_REC( 0x2CEB0, 0x2EBEF ), /* CJK Unified Ideographs Extension F */ + AF_UNIRANGE_REC( 0x2EBF0, 0x2EE5D ), /* CJK Unified Ideographs Extension I */ AF_UNIRANGE_REC( 0x2F800, 0x2FA1F ), /* CJK Compatibility Ideographs Supplement */ + AF_UNIRANGE_REC( 0x30000, 0x3134A ), /* CJK Unified Ideographs Extension G */ + AF_UNIRANGE_REC( 0x31350, 0x323AF ), /* CJK Unified Ideographs Extension H */ + AF_UNIRANGE_REC( 0x323B0, 0x33479 ), /* CJK Unified Ideographs Extension J */ AF_UNIRANGE_REC( 0, 0 ) }; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h index 813b3ee78ef..fa00eb75046 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h @@ -4,7 +4,7 @@ * * Auto-fitter Unicode script ranges (specification). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h index 0a83d771501..5c4cbbcb922 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h @@ -4,7 +4,7 @@ * * Auto-fitter scripts (specification only). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c index df0f46ada89..f3c0744fd9d 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (body). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -22,8 +22,8 @@ #include "aftypes.h" #include "afshaper.h" -#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ /************************************************************************** * @@ -89,17 +89,18 @@ #define SCRIPT( s, S, d, h, H, ss ) h, - static const hb_script_t scripts[] = + FT_LOCAL_ARRAY_DEF( hb_script_t ) + af_hb_scripts[] = { #include "afscript.h" }; - FT_Error - af_shaper_get_coverage( AF_FaceGlobals globals, - AF_StyleClass style_class, - FT_UShort* gstyles, - FT_Bool default_script ) + static FT_Error + af_shaper_get_coverage_hb( AF_FaceGlobals globals, + AF_StyleClass style_class, + FT_UShort* gstyles, + FT_Bool default_script ) { hb_face_t* face; @@ -124,10 +125,10 @@ if ( !globals || !style_class || !gstyles ) return FT_THROW( Invalid_Argument ); - face = hb_font_get_face( globals->hb_font ); + face = hb( font_get_face )( globals->hb_font ); coverage_tags = coverages[style_class->coverage]; - script = scripts[style_class->script]; + script = af_hb_scripts[style_class->script]; /* Convert a HarfBuzz script tag into the corresponding OpenType */ /* tag or tags -- some Indic scripts like Devanagari have an old */ @@ -137,19 +138,19 @@ hb_tag_t tags[3]; - hb_ot_tags_from_script_and_language( script, - HB_LANGUAGE_INVALID, - &tags_count, - tags, - NULL, - NULL ); + hb( ot_tags_from_script_and_language )( script, + HB_LANGUAGE_INVALID, + &tags_count, + tags, + NULL, + NULL ); script_tags[0] = tags_count > 0 ? tags[0] : HB_TAG_NONE; script_tags[1] = tags_count > 1 ? tags[1] : HB_TAG_NONE; script_tags[2] = tags_count > 2 ? tags[2] : HB_TAG_NONE; } - /* If the second tag is HB_OT_TAG_DEFAULT_SCRIPT, change that to */ - /* HB_TAG_NONE except for the default script. */ + /* If the second tag is HB_OT_TAG_DEFAULT_SCRIPT, change that to */ + /* HB_TAG_NONE except for the default script. */ if ( default_script ) { if ( script_tags[0] == HB_TAG_NONE ) @@ -170,15 +171,15 @@ goto Exit; } - gsub_lookups = hb_set_create(); - hb_ot_layout_collect_lookups( face, - HB_OT_TAG_GSUB, - script_tags, - NULL, - coverage_tags, - gsub_lookups ); + gsub_lookups = hb( set_create )(); + hb( ot_layout_collect_lookups )( face, + HB_OT_TAG_GSUB, + script_tags, + NULL, + coverage_tags, + gsub_lookups ); - if ( hb_set_is_empty( gsub_lookups ) ) + if ( hb( set_is_empty )( gsub_lookups ) ) goto Exit; /* nothing to do */ FT_TRACE4(( "GSUB lookups (style `%s'):\n", @@ -189,22 +190,22 @@ count = 0; #endif - gsub_glyphs = hb_set_create(); - for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, &idx ); ) + gsub_glyphs = hb( set_create )(); + for ( idx = HB_SET_VALUE_INVALID; hb( set_next )( gsub_lookups, &idx ); ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE4(( " %d", idx )); + FT_TRACE4(( " %u", idx )); count++; #endif /* get output coverage of GSUB feature */ - hb_ot_layout_lookup_collect_glyphs( face, - HB_OT_TAG_GSUB, - idx, - NULL, - NULL, - NULL, - gsub_glyphs ); + hb( ot_layout_lookup_collect_glyphs )( face, + HB_OT_TAG_GSUB, + idx, + NULL, + NULL, + NULL, + gsub_glyphs ); } #ifdef FT_DEBUG_LEVEL_TRACE @@ -218,34 +219,34 @@ af_style_names[style_class->style] )); FT_TRACE4(( " " )); - gpos_lookups = hb_set_create(); - hb_ot_layout_collect_lookups( face, - HB_OT_TAG_GPOS, - script_tags, - NULL, - coverage_tags, - gpos_lookups ); + gpos_lookups = hb( set_create )(); + hb( ot_layout_collect_lookups )( face, + HB_OT_TAG_GPOS, + script_tags, + NULL, + coverage_tags, + gpos_lookups ); #ifdef FT_DEBUG_LEVEL_TRACE count = 0; #endif - gpos_glyphs = hb_set_create(); - for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gpos_lookups, &idx ); ) + gpos_glyphs = hb( set_create )(); + for ( idx = HB_SET_VALUE_INVALID; hb( set_next )( gpos_lookups, &idx ); ) { #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE4(( " %d", idx )); + FT_TRACE4(( " %u", idx )); count++; #endif /* get input coverage of GPOS feature */ - hb_ot_layout_lookup_collect_glyphs( face, - HB_OT_TAG_GPOS, - idx, - NULL, - gpos_glyphs, - NULL, - NULL ); + hb( ot_layout_lookup_collect_glyphs )( face, + HB_OT_TAG_GPOS, + idx, + NULL, + gpos_glyphs, + NULL, + NULL ); } #ifdef FT_DEBUG_LEVEL_TRACE @@ -281,14 +282,14 @@ GET_UTF8_CHAR( ch, p ); - for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_lookups, - &idx ); ) + for ( idx = HB_SET_VALUE_INVALID; hb( set_next )( gsub_lookups, + &idx ); ) { hb_codepoint_t gidx = FT_Get_Char_Index( globals->face, ch ); - if ( hb_ot_layout_lookup_would_substitute( face, idx, - &gidx, 1, 1 ) ) + if ( hb( ot_layout_lookup_would_substitute )( face, idx, + &gidx, 1, 1 ) ) { found = 1; break; @@ -352,14 +353,14 @@ * */ if ( style_class->coverage != AF_COVERAGE_DEFAULT ) - hb_set_subtract( gsub_glyphs, gpos_glyphs ); + hb( set_subtract )( gsub_glyphs, gpos_glyphs ); #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE4(( " glyphs without GPOS data (`*' means already assigned)" )); count = 0; #endif - for ( idx = HB_SET_VALUE_INVALID; hb_set_next( gsub_glyphs, &idx ); ) + for ( idx = HB_SET_VALUE_INVALID; hb( set_next )( gsub_glyphs, &idx ); ) { #ifdef FT_DEBUG_LEVEL_TRACE if ( !( count % 10 ) ) @@ -368,7 +369,7 @@ FT_TRACE4(( " " )); } - FT_TRACE4(( " %d", idx )); + FT_TRACE4(( " %u", idx )); count++; #endif @@ -397,10 +398,10 @@ #endif Exit: - hb_set_destroy( gsub_lookups ); - hb_set_destroy( gsub_glyphs ); - hb_set_destroy( gpos_lookups ); - hb_set_destroy( gpos_glyphs ); + hb( set_destroy )( gsub_lookups ); + hb( set_destroy )( gsub_glyphs ); + hb( set_destroy )( gpos_lookups ); + hb( set_destroy )( gpos_glyphs ); return FT_Err_Ok; } @@ -437,31 +438,33 @@ }; - void* - af_shaper_buf_create( FT_Face face ) + static void* + af_shaper_buf_create_hb( AF_FaceGlobals globals ) { - FT_UNUSED( face ); + FT_UNUSED( globals ); - return (void*)hb_buffer_create(); + return (void*)hb( buffer_create )(); } - void - af_shaper_buf_destroy( FT_Face face, - void* buf ) + static void + af_shaper_buf_destroy_hb( AF_FaceGlobals globals, + void* buf ) { - FT_UNUSED( face ); + FT_UNUSED( globals ); - hb_buffer_destroy( (hb_buffer_t*)buf ); + hb( buffer_destroy )( (hb_buffer_t*)buf ); } - const char* - af_shaper_get_cluster( const char* p, - AF_StyleMetrics metrics, - void* buf_, - unsigned int* count ) + static const char* + af_shaper_get_cluster_hb( const char* p, + AF_StyleMetrics metrics, + void* buf_, + unsigned int* count ) { + AF_FaceGlobals globals = metrics->globals; + AF_StyleClass style_class; const hb_feature_t* feature; FT_Int upem; @@ -472,6 +475,8 @@ hb_font_t* font; hb_codepoint_t dummy; + FT_UNUSED( globals ); + upem = (FT_Int)metrics->globals->face->units_per_EM; style_class = metrics->style_class; @@ -480,7 +485,7 @@ font = metrics->globals->hb_font; /* we shape at a size of units per EM; this means font units */ - hb_font_set_scale( font, upem, upem ); + hb( font_set_scale )( font, upem, upem ); while ( *p == ' ' ) p++; @@ -492,15 +497,15 @@ len = (int)( q - p ); /* feed character(s) to the HarfBuzz buffer */ - hb_buffer_clear_contents( buf ); - hb_buffer_add_utf8( buf, p, len, 0, len ); + hb( buffer_clear_contents )( buf ); + hb( buffer_add_utf8 )( buf, p, len, 0, len ); /* we let HarfBuzz guess the script and writing direction */ - hb_buffer_guess_segment_properties( buf ); + hb( buffer_guess_segment_properties )( buf ); /* shape buffer, which means conversion from character codes to */ /* glyph indices, possibly applying a feature */ - hb_shape( font, buf, feature, feature ? 1 : 0 ); + hb( shape )( font, buf, feature, feature ? 1 : 0 ); if ( feature ) { @@ -517,13 +522,13 @@ /* glyph indices; otherwise the affected glyph or glyphs aren't */ /* available at all in the feature */ - hb_buffer_clear_contents( hb_buf ); - hb_buffer_add_utf8( hb_buf, p, len, 0, len ); - hb_buffer_guess_segment_properties( hb_buf ); - hb_shape( font, hb_buf, NULL, 0 ); + hb( buffer_clear_contents )( hb_buf ); + hb( buffer_add_utf8 )( hb_buf, p, len, 0, len ); + hb( buffer_guess_segment_properties )( hb_buf ); + hb( shape )( font, hb_buf, NULL, 0 ); - ginfo = hb_buffer_get_glyph_infos( buf, &gcount ); - hb_ginfo = hb_buffer_get_glyph_infos( hb_buf, &hb_gcount ); + ginfo = hb( buffer_get_glyph_infos )( buf, &gcount ); + hb_ginfo = hb( buffer_get_glyph_infos )( hb_buf, &hb_gcount ); if ( gcount == hb_gcount ) { @@ -537,12 +542,12 @@ if ( i == gcount ) { /* both buffers have identical glyph indices */ - hb_buffer_clear_contents( buf ); + hb( buffer_clear_contents )( buf ); } } } - *count = hb_buffer_get_length( buf ); + *count = hb( buffer_get_length )( buf ); #ifdef FT_DEBUG_LEVEL_TRACE if ( feature && *count > 1 ) @@ -554,23 +559,25 @@ } - FT_ULong - af_shaper_get_elem( AF_StyleMetrics metrics, - void* buf_, - unsigned int idx, - FT_Long* advance, - FT_Long* y_offset ) + static FT_ULong + af_shaper_get_elem_hb( AF_StyleMetrics metrics, + void* buf_, + unsigned int idx, + FT_Long* advance, + FT_Long* y_offset ) { + AF_FaceGlobals globals = metrics->globals; + hb_buffer_t* buf = (hb_buffer_t*)buf_; hb_glyph_info_t* ginfo; hb_glyph_position_t* gpos; unsigned int gcount; - FT_UNUSED( metrics ); + FT_UNUSED( globals ); - ginfo = hb_buffer_get_glyph_infos( buf, &gcount ); - gpos = hb_buffer_get_glyph_positions( buf, &gcount ); + ginfo = hb( buffer_get_glyph_infos )( buf, &gcount ); + gpos = hb( buffer_get_glyph_positions )( buf, &gcount ); if ( idx >= gcount ) return 0; @@ -584,14 +591,14 @@ } -#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ +#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */ - FT_Error - af_shaper_get_coverage( AF_FaceGlobals globals, - AF_StyleClass style_class, - FT_UShort* gstyles, - FT_Bool default_script ) + static FT_Error + af_shaper_get_coverage_nohb( AF_FaceGlobals globals, + AF_StyleClass style_class, + FT_UShort* gstyles, + FT_Bool default_script ) { FT_UNUSED( globals ); FT_UNUSED( style_class ); @@ -602,29 +609,29 @@ } - void* - af_shaper_buf_create( FT_Face face ) + static void* + af_shaper_buf_create_nohb( AF_FaceGlobals globals ) { - FT_UNUSED( face ); + FT_UNUSED( globals ); return NULL; } - void - af_shaper_buf_destroy( FT_Face face, - void* buf ) + static void + af_shaper_buf_destroy_nohb( AF_FaceGlobals globals, + void* buf ) { - FT_UNUSED( face ); + FT_UNUSED( globals ); FT_UNUSED( buf ); } - const char* - af_shaper_get_cluster( const char* p, - AF_StyleMetrics metrics, - void* buf_, - unsigned int* count ) + static const char* + af_shaper_get_cluster_nohb( const char* p, + AF_StyleMetrics metrics, + void* buf_, + unsigned int* count ) { FT_Face face = metrics->globals->face; FT_ULong ch, dummy = 0; @@ -656,12 +663,12 @@ } - FT_ULong - af_shaper_get_elem( AF_StyleMetrics metrics, - void* buf_, - unsigned int idx, - FT_Long* advance, - FT_Long* y_offset ) + static FT_ULong + af_shaper_get_elem_nohb( AF_StyleMetrics metrics, + void* buf_, + unsigned int idx, + FT_Long* advance, + FT_Long* y_offset ) { FT_Face face = metrics->globals->face; FT_ULong glyph_index = *(FT_ULong*)buf_; @@ -684,7 +691,90 @@ } -#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ */ + /********************************************************************/ + + FT_Error + af_shaper_get_coverage( AF_FaceGlobals globals, + AF_StyleClass style_class, + FT_UShort* gstyles, + FT_Bool default_script ) + { +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + if ( ft_hb_enabled( globals ) ) + return af_shaper_get_coverage_hb( globals, + style_class, + gstyles, + default_script ); + else +#endif + return af_shaper_get_coverage_nohb( globals, + style_class, + gstyles, + default_script ); + } + + + void* + af_shaper_buf_create( AF_FaceGlobals globals ) + { +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + if ( ft_hb_enabled( globals ) ) + return af_shaper_buf_create_hb( globals ); + else +#endif + return af_shaper_buf_create_nohb( globals ); + } + + + void + af_shaper_buf_destroy( AF_FaceGlobals globals, + void* buf ) + { +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + if ( ft_hb_enabled( globals ) ) + af_shaper_buf_destroy_hb( globals, buf ); + else +#endif + af_shaper_buf_destroy_nohb( globals, buf ); + } + + + const char* + af_shaper_get_cluster( const char* p, + AF_StyleMetrics metrics, + void* buf_, + unsigned int* count ) + { +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + if ( ft_hb_enabled( metrics->globals ) ) + return af_shaper_get_cluster_hb( p, metrics, buf_, count ); + else +#endif + return af_shaper_get_cluster_nohb( p, metrics, buf_, count ); + } + + + FT_ULong + af_shaper_get_elem( AF_StyleMetrics metrics, + void* buf_, + unsigned int idx, + FT_Long* advance, + FT_Long* y_offset ) + { +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + if ( ft_hb_enabled( metrics->globals ) ) + return af_shaper_get_elem_hb( metrics, + buf_, + idx, + advance, + y_offset ); +#endif + return af_shaper_get_elem_nohb( metrics, + buf_, + idx, + advance, + y_offset ); + } /* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h index 2eb03bb5d98..757368fc9c0 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h @@ -4,7 +4,7 @@ * * HarfBuzz interface for accessing OpenType features (specification). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -23,17 +23,14 @@ #include +FT_BEGIN_HEADER + #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ - -#include -#include -#include "ft-hb.h" - + FT_LOCAL_ARRAY( hb_script_t ) + af_hb_scripts[]; #endif -FT_BEGIN_HEADER - FT_Error af_shaper_get_coverage( AF_FaceGlobals globals, AF_StyleClass style_class, @@ -42,11 +39,11 @@ FT_BEGIN_HEADER void* - af_shaper_buf_create( FT_Face face ); + af_shaper_buf_create( AF_FaceGlobals globals ); void - af_shaper_buf_destroy( FT_Face face, - void* buf ); + af_shaper_buf_destroy( AF_FaceGlobals globals, + void* buf ); const char* af_shaper_get_cluster( const char* p, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h index 7a33f37a856..206232efe25 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h @@ -4,7 +4,7 @@ * * Auto-fitter styles (specification only). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -50,36 +50,36 @@ AF_COVERAGE_ ## C ) #undef META_STYLE_LATIN -#define META_STYLE_LATIN( s, S, ds ) \ - STYLE_LATIN( s, S, c2cp, C2CP, ds, \ +#define META_STYLE_LATIN( s, S, ds ) \ + STYLE_LATIN( s, S, c2cp, C2CP, ds, \ "petite capitals from capitals", \ - PETITE_CAPITALS_FROM_CAPITALS ) \ - STYLE_LATIN( s, S, c2sc, C2SC, ds, \ + PETITE_CAPITALS_FROM_CAPITALS ) \ + STYLE_LATIN( s, S, c2sc, C2SC, ds, \ "small capitals from capitals", \ - SMALL_CAPITALS_FROM_CAPITALS ) \ - STYLE_LATIN( s, S, ordn, ORDN, ds, \ - "ordinals", \ - ORDINALS ) \ - STYLE_LATIN( s, S, pcap, PCAP, ds, \ - "petite capitals", \ - PETITE_CAPITALS ) \ - STYLE_LATIN( s, S, sinf, SINF, ds, \ - "scientific inferiors", \ - SCIENTIFIC_INFERIORS ) \ - STYLE_LATIN( s, S, smcp, SMCP, ds, \ - "small capitals", \ - SMALL_CAPITALS ) \ - STYLE_LATIN( s, S, subs, SUBS, ds, \ - "subscript", \ - SUBSCRIPT ) \ - STYLE_LATIN( s, S, sups, SUPS, ds, \ - "superscript", \ - SUPERSCRIPT ) \ - STYLE_LATIN( s, S, titl, TITL, ds, \ - "titling", \ - TITLING ) \ - STYLE_LATIN( s, S, dflt, DFLT, ds, \ - "default", \ + SMALL_CAPITALS_FROM_CAPITALS ) \ + STYLE_LATIN( s, S, ordn, ORDN, ds, \ + "ordinals", \ + ORDINALS ) \ + STYLE_LATIN( s, S, pcap, PCAP, ds, \ + "petite capitals", \ + PETITE_CAPITALS ) \ + STYLE_LATIN( s, S, sinf, SINF, ds, \ + "scientific inferiors", \ + SCIENTIFIC_INFERIORS ) \ + STYLE_LATIN( s, S, smcp, SMCP, ds, \ + "small capitals", \ + SMALL_CAPITALS ) \ + STYLE_LATIN( s, S, subs, SUBS, ds, \ + "subscript", \ + SUBSCRIPT ) \ + STYLE_LATIN( s, S, sups, SUPS, ds, \ + "superscript", \ + SUPERSCRIPT ) \ + STYLE_LATIN( s, S, titl, TITL, ds, \ + "titling", \ + TITLING ) \ + STYLE_LATIN( s, S, dflt, DFLT, ds, \ + "default", \ DEFAULT ) diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h index 27e4185e9f8..959640a12ec 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h @@ -4,7 +4,7 @@ * * Auto-fitter types (specification only). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -406,6 +407,7 @@ extern void* af_debug_hints_; typedef struct AF_FaceGlobalsRec_* AF_FaceGlobals; + /* This is the main structure that combines everything. Autofit modules */ /* specific to writing systems derive their structures from it, for */ /* example `AF_LatinMetrics'. */ @@ -418,6 +420,8 @@ extern void* af_debug_hints_; AF_FaceGlobals globals; /* to access properties */ + FT_Hash reverse_charmap; + } AF_StyleMetricsRec; diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h index b78745af74e..12fa7a27a2b 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h @@ -4,7 +4,7 @@ * * Auto-fitter writing system declarations (specification only). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h index c86d609a352..1752697b375 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h @@ -4,7 +4,7 @@ * * Auto-fitter writing systems iterator (specification only). * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c new file mode 100644 index 00000000000..3c145d04640 --- /dev/null +++ b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.c @@ -0,0 +1,197 @@ +/**************************************************************************** + * + * ft-hb.c + * + * FreeType-HarfBuzz bridge (body). + * + * Copyright (C) 2025 by + * Behdad Esfahbod. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#if !defined( _WIN32 ) && !defined( _GNU_SOURCE ) +# define _GNU_SOURCE 1 /* for RTLD_DEFAULT */ +#endif + +#include +#include + +#include "afglobal.h" + +#include "ft-hb.h" + + +#if defined( FT_CONFIG_OPTION_USE_HARFBUZZ ) && \ + defined( FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC ) + +#ifndef FT_LIBHARFBUZZ +# ifdef _WIN32 +# define FT_LIBHARFBUZZ "libharfbuzz-0.dll" +# else +# ifdef __APPLE__ +# define FT_LIBHARFBUZZ "libharfbuzz.0.dylib" +# else +# define FT_LIBHARFBUZZ "libharfbuzz.so.0" +# endif +# endif +#endif + +#ifdef _WIN32 + +# include + +#else /* !_WIN32 */ + +# include + + /* The GCC pragma suppresses the warning "ISO C forbids */ + /* assignment between function pointer and 'void *'", which */ + /* inevitably gets emitted with `-Wpedantic`; see the man */ + /* page of function `dlsym` for more information. */ +# if defined( __GNUC__ ) +# pragma GCC diagnostic push +# ifndef __cplusplus +# pragma GCC diagnostic ignored "-Wpedantic" +# endif +# endif + +#endif /* !_WIN32 */ + + + FT_LOCAL_DEF( void ) + ft_hb_funcs_init( struct AF_ModuleRec_ *af_module ) + { + FT_Memory memory = af_module->root.memory; + FT_Error error; + + ft_hb_funcs_t *funcs = NULL; + ft_hb_version_atleast_func_t version_atleast = NULL; + +#ifdef _WIN32 + HANDLE lib; +# define DLSYM( lib, name ) \ + (ft_ ## name ## _func_t)GetProcAddress( lib, #name ) +#else + void *lib; +# define DLSYM( lib, name ) \ + (ft_ ## name ## _func_t)dlsym( lib, #name ) +#endif + + + af_module->hb_funcs = NULL; + + if ( FT_NEW( funcs ) ) + return; + FT_ZERO( funcs ); + +#ifdef _WIN32 + + lib = LoadLibraryA( FT_LIBHARFBUZZ ); + if ( !lib ) + goto Fail; + version_atleast = DLSYM( lib, hb_version_atleast ); + +#else /* !_WIN32 */ + +# ifdef RTLD_DEFAULT +# define FT_RTLD_FLAGS RTLD_LAZY | RTLD_GLOBAL + lib = RTLD_DEFAULT; + version_atleast = DLSYM( lib, hb_version_atleast ); +# else +# define FT_RTLD_FLAGS RTLD_LAZY +# endif + + if ( !version_atleast ) + { + /* Load the HarfBuzz library. + * + * We never close the library, since we opened it with RTLD_GLOBAL. + * This is important for the case where we are using HarfBuzz as a + * shared library, and we want to use the symbols from the library in + * other shared libraries or clients. HarfBuzz holds onto global + * variables, and closing the library will cause them to be + * invalidated. + */ + lib = dlopen( FT_LIBHARFBUZZ, FT_RTLD_FLAGS ); + if ( !lib ) + goto Fail; + version_atleast = DLSYM( lib, hb_version_atleast ); + } + +#endif /* !_WIN32 */ + + if ( !version_atleast ) + goto Fail; + + /* Load all symbols we use. */ +#define HB_EXTERN( ret, name, args ) \ + { \ + funcs->name = DLSYM( lib, name ); \ + if ( !funcs->name ) \ + goto Fail; \ + } +#include "ft-hb-decls.h" +#undef HB_EXTERN + +#undef DLSYM + + af_module->hb_funcs = funcs; + return; + + Fail: + if ( funcs ) + FT_FREE( funcs ); + } + + + FT_LOCAL_DEF( void ) + ft_hb_funcs_done( struct AF_ModuleRec_ *af_module ) + { + FT_Memory memory = af_module->root.memory; + + + if ( af_module->hb_funcs ) + { + FT_FREE( af_module->hb_funcs ); + af_module->hb_funcs = NULL; + } + } + + + FT_LOCAL_DEF( FT_Bool ) + ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals ) + { + return globals->module->hb_funcs != NULL; + } + +#ifndef _WIN32 +# if defined( __GNUC__ ) +# pragma GCC diagnostic pop +# endif +#endif + +#else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ + + FT_LOCAL_DEF( FT_Bool ) + ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals ) + { + FT_UNUSED( globals ); + +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + return TRUE; +#else + return FALSE; +#endif + } + +#endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ + + +/* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h new file mode 100644 index 00000000000..95914deb8d3 --- /dev/null +++ b/src/java.desktop/share/native/libfreetype/src/autofit/ft-hb.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * + * ft-hb.h + * + * FreeType-HarfBuzz bridge (specification). + * + * Copyright (C) 2025 by + * Behdad Esfahbod. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef FT_HB_H +#define FT_HB_H + +#include +#include + + +FT_BEGIN_HEADER + +#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ + +# include "ft-hb-types.h" + +# ifdef FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC + +# define HB_EXTERN( ret, name, args ) \ + typedef ret (*ft_ ## name ## _func_t) args; +# include "ft-hb-decls.h" +# undef HB_EXTERN + + typedef struct ft_hb_funcs_t + { +# define HB_EXTERN( ret, name, args ) \ + ft_ ## name ## _func_t name; +# include "ft-hb-decls.h" +# undef HB_EXTERN + } ft_hb_funcs_t; + + struct AF_ModuleRec_; + + FT_LOCAL( void ) + ft_hb_funcs_init( struct AF_ModuleRec_ *af_module ); + + FT_LOCAL( void ) + ft_hb_funcs_done( struct AF_ModuleRec_ *af_module ); + +# define hb( x ) globals->module->hb_funcs->hb_ ## x + +# else /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ + +# define HB_EXTERN( ret, name, args ) \ + ret name args; +# include "ft-hb-decls.h" +# undef HB_EXTERN + +# define hb( x ) hb_ ## x + +# endif /* !FT_CONFIG_OPTION_USE_HARFBUZZ_DYNAMIC */ + +#endif /* FT_CONFIG_OPTION_USE_HARFBUZZ */ + + + struct AF_FaceGlobalsRec_; + + FT_LOCAL( FT_Bool ) + ft_hb_enabled( struct AF_FaceGlobalsRec_ *globals ); + + +FT_END_HEADER + +#endif /* FT_HB_H */ + + +/* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c index 717f7d08b35..ff0fc510503 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c @@ -4,7 +4,7 @@ * * Quick computation of advance widths (body). * - * Copyright (C) 2008-2024 by + * Copyright (C) 2008-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h index 1d98b26dd51..66f091165fe 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h @@ -4,7 +4,7 @@ * * Private functions used in the `base' module (specification). * - * Copyright (C) 2008-2024 by + * Copyright (C) 2008-2025 by * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. * * This file is part of the FreeType project, and may only be used, @@ -34,7 +34,7 @@ FT_BEGIN_HEADER #ifdef FT_CONFIG_OPTION_MAC_FONTS /* MacOS resource fork cannot exceed 16MB at least for Carbon code; */ - /* see https://support.microsoft.com/en-us/kb/130437 */ + /* see https://jeffpar.github.io/kbarchive/kb/130/Q130437/ */ #define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c index d6aa5d56df8..feccdee5dd7 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c @@ -4,7 +4,7 @@ * * FreeType bbox computation (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c index 4be145679fd..2c8e44b905d 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c @@ -4,7 +4,7 @@ * * FreeType utility functions for bitmaps (body). * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -876,13 +876,13 @@ #ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE5(( "FT_Bitmap_Blend:\n" )); - FT_TRACE5(( " source bitmap: (%ld, %ld) -- (%ld, %ld); %d x %d\n", + FT_TRACE5(( " source bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", source_llx / 64, source_lly / 64, source_urx / 64, source_ury / 64, source_->width, source_->rows )); if ( target->width && target->rows ) - FT_TRACE5(( " target bitmap: (%ld, %ld) -- (%ld, %ld); %d x %d\n", + FT_TRACE5(( " target bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", target_llx / 64, target_lly / 64, target_urx / 64, target_ury / 64, target->width, target->rows )); @@ -890,7 +890,7 @@ FT_TRACE5(( " target bitmap: empty\n" )); if ( final_width && final_rows ) - FT_TRACE5(( " final bitmap: (%ld, %ld) -- (%ld, %ld); %d x %d\n", + FT_TRACE5(( " final bitmap: (%ld, %ld) -- (%ld, %ld); %u x %u\n", final_llx / 64, final_lly / 64, final_urx / 64, final_ury / 64, final_width, final_rows )); @@ -924,7 +924,7 @@ if ( FT_LONG_MAX / target->pitch < (int)target->rows ) { - FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n", + FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%u x %u)\n", final_width, final_rows )); return FT_THROW( Invalid_Argument ); } @@ -952,7 +952,7 @@ if ( FT_LONG_MAX / new_pitch < (int)final_rows ) { - FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%d x %d)\n", + FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%u x %u)\n", final_width, final_rows )); return FT_THROW( Invalid_Argument ); } diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c index 92de09ed877..7d6e12e2543 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c @@ -4,7 +4,7 @@ * * Arithmetic computations (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -38,24 +38,11 @@ #include #include - -#ifdef FT_MULFIX_ASSEMBLER -#undef FT_MulFix + /* cancel inlining macro from internal/ftcalc.h */ +#ifdef FT_MulFix +# undef FT_MulFix #endif -/* we need to emulate a 64-bit data type if a real one isn't available */ - -#ifndef FT_INT64 - - typedef struct FT_Int64_ - { - FT_UInt32 lo; - FT_UInt32 hi; - - } FT_Int64; - -#endif /* !FT_INT64 */ - /************************************************************************** * @@ -88,7 +75,7 @@ FT_EXPORT_DEF( FT_Fixed ) FT_RoundFix( FT_Fixed a ) { - return ( ADD_LONG( a, 0x8000L - ( a < 0 ) ) ) & ~0xFFFFL; + return ADD_LONG( a, 0x8000L - ( a < 0 ) ) & ~0xFFFFL; } @@ -97,7 +84,7 @@ FT_EXPORT_DEF( FT_Fixed ) FT_CeilFix( FT_Fixed a ) { - return ( ADD_LONG( a, 0xFFFFL ) ) & ~0xFFFFL; + return ADD_LONG( a, 0xFFFFL ) & ~0xFFFFL; } @@ -225,18 +212,18 @@ FT_MulFix( FT_Long a_, FT_Long b_ ) { -#ifdef FT_MULFIX_ASSEMBLER +#ifdef FT_CONFIG_OPTION_INLINE_MULFIX - return FT_MULFIX_ASSEMBLER( (FT_Int32)a_, (FT_Int32)b_ ); + return FT_MulFix_64( a_, b_ ); #else - FT_Int64 ab = (FT_Int64)a_ * (FT_Int64)b_; + FT_Int64 ab = MUL_INT64( a_, b_ ); /* this requires arithmetic right shift of signed numbers */ - return (FT_Long)( ( ab + 0x8000L - ( ab < 0 ) ) >> 16 ); + return (FT_Long)( ( ab + 0x8000L + ( ab >> 63 ) ) >> 16 ); -#endif /* FT_MULFIX_ASSEMBLER */ +#endif /* FT_CONFIG_OPTION_INLINE_MULFIX */ } @@ -975,43 +962,36 @@ #else - FT_Int result; + FT_Int64 z1, z2; + FT_Int result; - if ( ADD_LONG( FT_ABS( in_x ), FT_ABS( out_y ) ) <= 131071L && - ADD_LONG( FT_ABS( in_y ), FT_ABS( out_x ) ) <= 131071L ) + if ( (FT_ULong)FT_ABS( in_x ) + (FT_ULong)FT_ABS( out_y ) <= 92681UL ) { - FT_Long z1 = MUL_LONG( in_x, out_y ); - FT_Long z2 = MUL_LONG( in_y, out_x ); - - - if ( z1 > z2 ) - result = +1; - else if ( z1 < z2 ) - result = -1; - else - result = 0; + z1.lo = (FT_UInt32)in_x * (FT_UInt32)out_y; + z1.hi = (FT_UInt32)( (FT_Int32)z1.lo >> 31 ); /* sign-expansion */ } - else /* products might overflow 32 bits */ - { - FT_Int64 z1, z2; - - - /* XXX: this function does not allow 64-bit arguments */ + else ft_multo64( (FT_UInt32)in_x, (FT_UInt32)out_y, &z1 ); + + if ( (FT_ULong)FT_ABS( in_y ) + (FT_ULong)FT_ABS( out_x ) <= 92681UL ) + { + z2.lo = (FT_UInt32)in_y * (FT_UInt32)out_x; + z2.hi = (FT_UInt32)( (FT_Int32)z2.lo >> 31 ); /* sign-expansion */ + } + else ft_multo64( (FT_UInt32)in_y, (FT_UInt32)out_x, &z2 ); - if ( z1.hi > z2.hi ) - result = +1; - else if ( z1.hi < z2.hi ) - result = -1; - else if ( z1.lo > z2.lo ) - result = +1; - else if ( z1.lo < z2.lo ) - result = -1; - else - result = 0; - } + if ( (FT_Int32)z1.hi > (FT_Int32)z2.hi ) + result = +1; + else if ( (FT_Int32)z1.hi < (FT_Int32)z2.hi ) + result = -1; + else if ( z1.lo > z2.lo ) + result = +1; + else if ( z1.lo < z2.lo ) + result = -1; + else + result = 0; /* XXX: only the sign of return value, +1/0/-1 must be used */ return result; @@ -1065,62 +1045,4 @@ } - FT_BASE_DEF( FT_Int32 ) - FT_MulAddFix( FT_Fixed* s, - FT_Int32* f, - FT_UInt count ) - { - FT_UInt i; - FT_Int64 temp; - - -#ifdef FT_INT64 - temp = 0; - - for ( i = 0; i < count; ++i ) - temp += (FT_Int64)s[i] * f[i]; - - return (FT_Int32)( ( temp + 0x8000 ) >> 16 ); -#else - temp.hi = 0; - temp.lo = 0; - - for ( i = 0; i < count; ++i ) - { - FT_Int64 multResult; - - FT_Int sign = 1; - FT_UInt32 carry = 0; - - FT_UInt32 scalar; - FT_UInt32 factor; - - - FT_MOVE_SIGN( FT_UInt32, s[i], scalar, sign ); - FT_MOVE_SIGN( FT_UInt32, f[i], factor, sign ); - - ft_multo64( scalar, factor, &multResult ); - - if ( sign < 0 ) - { - /* Emulated `FT_Int64` negation. */ - carry = ( multResult.lo == 0 ); - - multResult.lo = ~multResult.lo + 1; - multResult.hi = ~multResult.hi + carry; - } - - FT_Add64( &temp, &multResult, &temp ); - } - - /* Shift and round value. */ - return (FT_Int32)( ( ( temp.hi << 16 ) | ( temp.lo >> 16 ) ) - + ( 1 & ( temp.lo >> 15 ) ) ); - - -#endif /* !FT_INT64 */ - - } - - /* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c index 4f2deb19a05..35cd0fcd2be 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c @@ -4,7 +4,7 @@ * * FreeType API for accessing CID font information. * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * Derek Clegg and Michael Toftdal. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c index c6bf2a3cd1a..90b02b7d2de 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c @@ -4,7 +4,7 @@ * * FreeType's glyph color management (body). * - * Copyright (C) 2018-2024 by + * Copyright (C) 2018-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -56,9 +56,7 @@ FT_Color* *apalette ) { FT_Error error; - - TT_Face ttface; - SFNT_Service sfnt; + TT_Face ttface = (TT_Face)face; if ( !face ) @@ -72,14 +70,17 @@ return FT_Err_Ok; } - ttface = (TT_Face)face; - sfnt = (SFNT_Service)ttface->sfnt; + if ( palette_index != ttface->palette_index ) + { + SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; - error = sfnt->set_palette( ttface, palette_index ); - if ( error ) - return error; - ttface->palette_index = palette_index; + error = sfnt->set_palette( ttface, palette_index ); + if ( error ) + return error; + + ttface->palette_index = palette_index; + } if ( apalette ) *apalette = ttface->palette; diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c index 902a5dc8bbc..7f54e759b16 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c @@ -4,7 +4,7 @@ * * Memory debugger (body). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -139,7 +139,6 @@ } FT_MemTableRec; -#define FT_MEM_SIZE_MIN 7 #define FT_MEM_SIZE_MAX 13845163 #define FT_FILENAME( x ) ( (x) ? (x) : "unknown file" ) diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c index 11307eaace4..c615f29e521 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c @@ -4,7 +4,7 @@ * * Debugging and logging component (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -64,7 +64,7 @@ * with the actual log message if set to true. * * 5. The flag `ft_timestamp_flag` prints time along with the actual log - * message if set to ture. + * message if set to true. * * 6. `ft_have_newline_char` is used to differentiate between a log * message with and without a trailing newline character. diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c index 77b4089e7e2..7f4f14ffdb0 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c @@ -4,7 +4,7 @@ * * FreeType utility file for font formats (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c index 1565c3b7e25..3a95752ffaa 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c @@ -4,7 +4,7 @@ * * FreeType utility file to access FSType data (body). * - * Copyright (C) 2008-2024 by + * Copyright (C) 2008-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c index c63d30e978c..2202240b57e 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c @@ -4,7 +4,7 @@ * * Access of TrueType's `gasp' table (body). * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c index 484d98f1722..47781bc4d5c 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c @@ -4,7 +4,7 @@ * * The FreeType glyph loader (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c index 1b5849f99af..75babb1aa56 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c @@ -4,7 +4,7 @@ * * FreeType convenience functions to handle glyphs (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/fthash.c b/src/java.desktop/share/native/libfreetype/src/base/fthash.c index 313bbbb4b27..ab248ace8bd 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/fthash.c +++ b/src/java.desktop/share/native/libfreetype/src/base/fthash.c @@ -41,6 +41,7 @@ #include #include +#include #define INITIAL_HT_SIZE 241 @@ -233,7 +234,8 @@ hash_insert( FT_Hashkey key, size_t data, FT_Hash hash, - FT_Memory memory ) + FT_Memory memory, + FT_Bool overwrite ) { FT_Hashnode nn; FT_Hashnode* bp = hash_bucket( key, hash ); @@ -259,7 +261,7 @@ hash->used++; } - else + else if ( overwrite ) nn->data = data; Exit: @@ -278,7 +280,7 @@ hk.str = key; - return hash_insert( hk, data, hash, memory ); + return hash_insert( hk, data, hash, memory, TRUE ); } @@ -293,7 +295,37 @@ hk.num = num; - return hash_insert( hk, data, hash, memory ); + return hash_insert( hk, data, hash, memory, TRUE ); + } + + + FT_Error + ft_hash_str_insert_no_overwrite( const char* key, + size_t data, + FT_Hash hash, + FT_Memory memory ) + { + FT_Hashkey hk; + + + hk.str = key; + + return hash_insert( hk, data, hash, memory, FALSE ); + } + + + FT_Error + ft_hash_num_insert_no_overwrite( FT_Int num, + size_t data, + FT_Hash hash, + FT_Memory memory ) + { + FT_Hashkey hk; + + + hk.num = num; + + return hash_insert( hk, data, hash, memory, FALSE ); } @@ -335,4 +367,68 @@ } + FT_Bool + ft_hash_num_iterator( FT_UInt *idx, + FT_Int *key, + size_t *value, + FT_Hash hash ) + { + FT_Hashnode nn = NULL; + + + while ( 1 ) + { + if ( *idx >= hash->size ) + return 0; + + nn = hash->table[*idx]; + if ( nn ) + break; + + (*idx)++; + } + + if ( key ) + *key = nn->key.num; + if ( value ) + *value = nn->data; + + (*idx)++; + + return 1; + } + + + FT_Bool + ft_hash_str_iterator( FT_UInt *idx, + const char* *key, + size_t *value, + FT_Hash hash ) + { + FT_Hashnode nn = NULL; + + + while ( 1 ) + { + if ( *idx >= hash->size ) + return 0; + + nn = hash->table[*idx]; + if ( nn ) + break; + + (*idx)++; + } + + if ( key ) + *key = nn->key.str; + if ( value ) + *value = nn->data; + + (*idx)++; + + return 1; + } + + /* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c index 9a6c00e13ef..37d7f87bcb9 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c @@ -4,7 +4,7 @@ * * FreeType initialization layer (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c index 1e69d4da70f..d026da8b012 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c @@ -4,7 +4,7 @@ * * FreeType API for color filtering of subpixel bitmap glyphs (body). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c index e8e35627b50..37d97be1838 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c @@ -8,7 +8,7 @@ * This file is for Mac OS X only; see builds/mac/ftoldmac.c for * classic platforms built by MPW. * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c index cc4ca22fba3..9e67001406c 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c @@ -4,7 +4,7 @@ * * Multiple Master font support (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -292,6 +292,9 @@ if ( num_coords && !coords ) return FT_THROW( Invalid_Argument ); + if ( !num_coords && !FT_IS_VARIATION( face ) ) + return FT_Err_Ok; /* nothing to be done */ + error = ft_face_get_mm_service( face, &service_mm ); if ( !error ) { @@ -299,15 +302,21 @@ if ( service_mm->set_var_design ) error = service_mm->set_var_design( face, num_coords, coords ); - if ( !error || error == -1 ) + if ( !error || error == -1 || error == -2 ) { FT_Bool is_variation_old = FT_IS_VARIATION( face ); - if ( num_coords ) - face->face_flags |= FT_FACE_FLAG_VARIATION; - else - face->face_flags &= ~FT_FACE_FLAG_VARIATION; + if ( error != -1 ) + { + if ( error == -2 ) /* -2 means is_variable. */ + { + face->face_flags |= FT_FACE_FLAG_VARIATION; + error = FT_Err_Ok; + } + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } if ( service_mm->construct_ps_name ) { @@ -474,15 +483,21 @@ if ( service_mm->set_mm_blend ) error = service_mm->set_mm_blend( face, num_coords, coords ); - if ( !error || error == -1 ) + if ( !error || error == -1 || error == -2 ) { FT_Bool is_variation_old = FT_IS_VARIATION( face ); - if ( num_coords ) - face->face_flags |= FT_FACE_FLAG_VARIATION; - else - face->face_flags &= ~FT_FACE_FLAG_VARIATION; + if ( error != -1 ) + { + if ( error == -2 ) /* -2 means is_variable. */ + { + face->face_flags |= FT_FACE_FLAG_VARIATION; + error = FT_Err_Ok; + } + else + face->face_flags &= ~FT_FACE_FLAG_VARIATION; + } if ( service_mm->construct_ps_name ) { diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c index 9b97820c379..cced4fed06b 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c @@ -4,7 +4,7 @@ * * The FreeType private base classes (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -905,7 +905,6 @@ FT_Library library; FT_Bool autohint = FALSE; FT_Module hinter; - TT_Face ttface = (TT_Face)face; if ( !face || !face->size || !face->glyph ) @@ -983,6 +982,7 @@ { FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); FT_Bool is_light_type1; + TT_Face ttface = (TT_Face)face; /* only the new Adobe engine (for both CFF and Type 1) is `light'; */ @@ -994,8 +994,7 @@ /* the check for `num_locations' assures that we actually */ /* test for instructions in a TTF and not in a CFF-based OTF */ /* */ - /* since `maxSizeOfInstructions' might be unreliable, we */ - /* check the size of the `fpgm' and `prep' tables, too -- */ + /* we check the size of the `fpgm' and `prep' tables, too -- */ /* the assumption is that there don't exist real TTFs where */ /* both `fpgm' and `prep' tables are missing */ if ( ( mode == FT_RENDER_MODE_LIGHT && @@ -1003,9 +1002,8 @@ !is_light_type1 ) ) || ( FT_IS_SFNT( face ) && ttface->num_locations && - ttface->max_profile.maxSizeOfInstructions == 0 && ttface->font_program_size == 0 && - ttface->cvt_program_size == 0 ) ) + ttface->cvt_program_size <= 7 ) ) autohint = TRUE; } } @@ -1172,9 +1170,9 @@ } #ifdef FT_DEBUG_LEVEL_TRACE - FT_TRACE5(( "FT_Load_Glyph: index %d, flags 0x%x\n", + FT_TRACE5(( "FT_Load_Glyph: index %u, flags 0x%x\n", glyph_index, load_flags )); - FT_TRACE5(( " bitmap %dx%d %s, %s (mode %d)\n", + FT_TRACE5(( " bitmap %ux%u %s, %s (mode %d)\n", slot->bitmap.width, slot->bitmap.rows, slot->outline.points ? @@ -1253,14 +1251,14 @@ FT_Driver driver = (FT_Driver)driver_; - /* finalize client-specific data */ - if ( size->generic.finalizer ) - size->generic.finalizer( size ); - /* finalize format-specific stuff */ if ( driver->clazz->done_size ) driver->clazz->done_size( size ); + /* finalize client-specific data */ + if ( size->generic.finalizer ) + size->generic.finalizer( size ); + FT_FREE( size->internal ); FT_FREE( size ); } @@ -1322,10 +1320,6 @@ driver ); face->size = NULL; - /* now discard client data */ - if ( face->generic.finalizer ) - face->generic.finalizer( face ); - /* discard charmaps */ destroy_charmaps( face, memory ); @@ -1340,6 +1334,10 @@ face->stream = NULL; + /* now discard client data */ + if ( face->generic.finalizer ) + face->generic.finalizer( face ); + /* get rid of it */ if ( face->internal ) { @@ -1359,21 +1357,9 @@ } - /************************************************************************** - * - * @Function: - * find_unicode_charmap - * - * @Description: - * This function finds a Unicode charmap, if there is one. - * And if there is more than one, it tries to favour the more - * extensive one, i.e., one that supports UCS-4 against those which - * are limited to the BMP (said UCS-2 encoding.) - * - * This function is called from open_face() (just below), and also - * from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). - */ - static FT_Error + /* documentation is in ftobjs.h */ + + FT_BASE_DEF( FT_Error ) find_unicode_charmap( FT_Face face ) { FT_CharMap* first; @@ -2125,7 +2111,7 @@ if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len ) goto Exit2; - FT_TRACE3(( " Load POST fragment #%d (%ld byte) to buffer" + FT_TRACE3(( " Load POST fragment #%d (%lu byte) to buffer" " %p + 0x%08lx\n", i, rlen, (void*)pfb_data, pfb_pos )); @@ -2398,7 +2384,7 @@ is_darwin_vfs = ft_raccess_rule_by_darwin_vfs( library, i ); if ( is_darwin_vfs && vfs_rfork_has_no_font ) { - FT_TRACE3(( "Skip rule %d: darwin vfs resource fork" + FT_TRACE3(( "Skip rule %u: darwin vfs resource fork" " is already checked and" " no font is found\n", i )); @@ -2407,7 +2393,7 @@ if ( errors[i] ) { - FT_TRACE3(( "Error 0x%x has occurred in rule %d\n", + FT_TRACE3(( "Error 0x%x has occurred in rule %u\n", errors[i], i )); continue; } @@ -2415,7 +2401,7 @@ args2.flags = FT_OPEN_PATHNAME; args2.pathname = file_names[i] ? file_names[i] : args->pathname; - FT_TRACE3(( "Try rule %d: %s (offset=%ld) ...", + FT_TRACE3(( "Try rule %u: %s (offset=%ld) ...", i, args2.pathname, offsets[i] )); error = FT_Stream_New( library, &args2, &stream2 ); @@ -5044,9 +5030,9 @@ static void Destroy_Module( FT_Module module ) { - FT_Memory memory = module->memory; - FT_Module_Class* clazz = module->clazz; - FT_Library library = module->library; + const FT_Module_Class* clazz = module->clazz; + FT_Library library = module->library; + FT_Memory memory = module->memory; if ( library && library->auto_hinter == module ) @@ -5125,9 +5111,9 @@ goto Exit; /* base initialization */ + module->clazz = clazz; module->library = library; module->memory = memory; - module->clazz = (FT_Module_Class*)clazz; /* check whether the module is a renderer - this must be performed */ /* before the normal module initialization */ diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c index ef699b3c7cd..8a15b03eb83 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c @@ -4,7 +4,7 @@ * * FreeType outline management (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c index 2055757e023..664bc34deea 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c @@ -5,7 +5,7 @@ * FreeType API for checking patented TrueType bytecode instructions * (body). Obsolete, retained for backward compatibility. * - * Copyright (C) 2007-2024 by + * Copyright (C) 2007-2025 by * David Turner. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c index 37a6cee6cc9..0631cd63f62 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c @@ -5,7 +5,7 @@ * Get and set properties of PostScript drivers (body). * See `ftdriver.h' for available properties. * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c index dc9b043d8bb..1e241f4f95b 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c @@ -4,7 +4,7 @@ * * Embedded resource forks accessor (body). * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * Masatake YAMATO and Redhat K.K. * * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are @@ -269,14 +269,8 @@ * According to Inside Macintosh: More Macintosh Toolbox, * "Resource IDs" (1-46), there are some reserved IDs. * However, FreeType2 is not a font synthesizer, no need - * to check the acceptable resource ID. + * to check the acceptable resource ID or its attributes. */ - if ( temp < 0 ) - { - error = FT_THROW( Invalid_Table ); - goto Exit; - } - ref[j].offset = temp & 0xFFFFFFL; FT_TRACE3(( " [%d]:" diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c index f7231fd61cc..34a67a148fc 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c @@ -7,7 +7,7 @@ * * This is _not_ used to retrieve glyph names! * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c index 66722246128..c04a0506def 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c @@ -4,7 +4,7 @@ * * I/O stream support (body). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -242,7 +242,7 @@ FT_ULong read_bytes; - FT_TRACE7(( "FT_Stream_EnterFrame: %ld bytes\n", count )); + FT_TRACE7(( "FT_Stream_EnterFrame: %lu bytes\n", count )); /* check for nested frame access */ FT_ASSERT( stream && stream->cursor == 0 ); diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c index 64f46ce43e7..591f18eaa83 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c @@ -4,7 +4,7 @@ * * FreeType path stroker (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1070,7 +1070,7 @@ if ( theta == FT_ANGLE_PI2 ) theta = -rotate; - phi = stroker->angle_in + theta + rotate; + phi = stroker->angle_in + theta + rotate; FT_Vector_From_Polar( &sigma, stroker->miter_limit, theta ); @@ -1371,7 +1371,7 @@ arc[1] = *control; arc[2] = stroker->center; - while ( arc >= bez_stack ) + do { FT_Angle angle_in, angle_out; @@ -1524,10 +1524,12 @@ } } - arc -= 2; - stroker->angle_in = angle_out; - } + + if ( arc == bez_stack ) + break; + arc -= 2; + } while ( 1 ); stroker->center = *to; stroker->line_length = 0; @@ -1577,7 +1579,7 @@ arc[2] = *control1; arc[3] = stroker->center; - while ( arc >= bez_stack ) + do { FT_Angle angle_in, angle_mid, angle_out; @@ -1741,10 +1743,12 @@ } } - arc -= 3; - stroker->angle_in = angle_out; - } + + if ( arc == bez_stack ) + break; + arc -= 3; + } while ( 1 ); stroker->center = *to; stroker->line_length = 0; diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c index ec05bce33a9..08bc1742202 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c @@ -4,7 +4,7 @@ * * FreeType synthesizing code for emboldening and slanting (body). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -141,7 +141,7 @@ /* * XXX: overflow check for 16-bit system, for compatibility * with FT_GlyphSlot_Embolden() since FreeType 2.1.10. - * unfortunately, this function return no informations + * unfortunately, this function returns no information * about the cause of error. */ if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN ) diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c index eee3642334f..186119d5581 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c @@ -4,7 +4,7 @@ * * ANSI-specific FreeType low-level system interface (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -280,7 +280,7 @@ stream->close = ft_ansi_stream_close; FT_TRACE1(( "FT_Stream_Open:" )); - FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n", + FT_TRACE1(( " opened `%s' (%lu bytes) successfully\n", filepathname, stream->size )); return FT_Err_Ok; diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c index 4b1aced1cba..29eff639c51 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c +++ b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c @@ -4,7 +4,7 @@ * * FreeType trigonometric functions (body). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c index cedf7c40505..77978df674d 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c +++ b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c @@ -4,7 +4,7 @@ * * FreeType utility file for PS names support (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c index b13512f8704..0b7382627c5 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c @@ -4,7 +4,7 @@ * * FreeType utility file for memory and list management (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c index ea5f8ed2885..cb69abdb90f 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h index 1dd8700cd8b..60e16d94875 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h @@ -4,7 +4,7 @@ * * CFF character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c index f6ebdb3810a..0079ddd1950 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c @@ -4,7 +4,7 @@ * * OpenType font driver implementation (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. * * This file is part of the FreeType project, and may only be used, @@ -121,7 +121,20 @@ kerning->y = 0; if ( sfnt ) - kerning->x = sfnt->get_kerning( cffface, left_glyph, right_glyph ); + { + /* Use 'kern' table if available since that can be faster; otherwise */ + /* use GPOS kerning pairs if available. */ + if ( cffface->kern_avail_bits ) + kerning->x = sfnt->get_kerning( cffface, + left_glyph, + right_glyph ); +#ifdef TT_CONFIG_OPTION_GPOS_KERNING + else if ( cffface->num_gpos_lookups_kerning ) + kerning->x = sfnt->get_gpos_kerning( cffface, + left_glyph, + right_glyph ); +#endif + } return FT_Err_Ok; } @@ -168,25 +181,7 @@ CFF_Size cffsize = (CFF_Size)size; - if ( !cffslot ) - return FT_THROW( Invalid_Slot_Handle ); - - FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); - - /* check whether we want a scaled outline or bitmap */ - if ( !cffsize ) - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; - - /* reset the size object if necessary */ - if ( load_flags & FT_LOAD_NO_SCALE ) - size = NULL; - - if ( size ) - { - /* these two objects must have the same parent */ - if ( size->face != slot->face ) - return FT_THROW( Invalid_Face_Handle ); - } + FT_TRACE1(( "cff_glyph_load: glyph index %u\n", glyph_index )); /* now load the glyph outline if necessary */ error = cff_slot_load( cffslot, cffsize, glyph_index, load_flags ); @@ -205,105 +200,70 @@ FT_Int32 flags, FT_Fixed* advances ) { - FT_UInt nn; - FT_Error error = FT_Err_Ok; - FT_GlyphSlot slot = face->glyph; + CFF_Face cffface = (CFF_Face)face; + FT_Bool horz; + FT_UInt nn; - if ( FT_IS_SFNT( face ) ) + if ( !FT_IS_SFNT( face ) ) + return FT_THROW( Unimplemented_Feature ); + + horz = !( flags & FT_LOAD_VERTICAL_LAYOUT ); + + if ( horz ) { /* OpenType 1.7 mandates that the data from `hmtx' table be used; */ /* it is no longer necessary that those values are identical to */ /* the values in the `CFF' table */ + if ( !cffface->horizontal.number_Of_HMetrics ) + return FT_THROW( Unimplemented_Feature ); - CFF_Face cffface = (CFF_Face)face; - FT_Short dummy; - - - if ( flags & FT_LOAD_VERTICAL_LAYOUT ) - { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - /* no fast retrieval for blended MM fonts without VVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( cffface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) - return FT_THROW( Unimplemented_Feature ); + /* no fast retrieval for blended MM fonts without HVAR table */ + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( cffface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) + return FT_THROW( Unimplemented_Feature ); #endif + } + else /* vertical */ + { + /* check whether we have data from the `vmtx' table at all; */ + /* otherwise we extract the info from the CFF glyphstrings */ + /* (instead of synthesizing a global value using the `OS/2' */ + /* table) */ + if ( !cffface->vertical_info ) + return FT_THROW( Unimplemented_Feature ); - /* check whether we have data from the `vmtx' table at all; */ - /* otherwise we extract the info from the CFF glyphstrings */ - /* (instead of synthesizing a global value using the `OS/2' */ - /* table) */ - if ( !cffface->vertical_info ) - goto Missing_Table; - - for ( nn = 0; nn < count; nn++ ) - { - FT_UShort ah; - - - ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, - 1, - start + nn, - &dummy, - &ah ); - - FT_TRACE5(( " idx %d: advance height %d font unit%s\n", - start + nn, - ah, - ah == 1 ? "" : "s" )); - advances[nn] = ah; - } - } - else - { #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - /* no fast retrieval for blended MM fonts without HVAR table */ - if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && - !( cffface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) - return FT_THROW( Unimplemented_Feature ); + /* no fast retrieval for blended MM fonts without VVAR table */ + if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && + !( cffface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) + return FT_THROW( Unimplemented_Feature ); #endif - - /* check whether we have data from the `hmtx' table at all */ - if ( !cffface->horizontal.number_Of_HMetrics ) - goto Missing_Table; - - for ( nn = 0; nn < count; nn++ ) - { - FT_UShort aw; - - - ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, - 0, - start + nn, - &dummy, - &aw ); - - FT_TRACE5(( " idx %d: advance width %d font unit%s\n", - start + nn, - aw, - aw == 1 ? "" : "s" )); - advances[nn] = aw; - } - } - - return error; } - Missing_Table: - flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; - + /* proceed to fast advances */ for ( nn = 0; nn < count; nn++ ) { - error = cff_glyph_load( slot, face->size, start + nn, flags ); - if ( error ) - break; + FT_UShort aw; + FT_Short dummy; - advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) - ? slot->linearVertAdvance - : slot->linearHoriAdvance; + + ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, + !horz, + start + nn, + &dummy, + &aw ); + + FT_TRACE5(( " idx %u: advance %s %d font unit%s\n", + start + nn, + horz ? "width" : "height", + aw, + aw == 1 ? "" : "s" )); + advances[nn] = aw; } - return error; + return FT_Err_Ok; } diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h index fd5bc37ecd4..52a1e727a6a 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h @@ -4,7 +4,7 @@ * * High-level OpenType driver interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h index 128adc3b716..7491886c7be 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h @@ -4,7 +4,7 @@ * * CFF error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c index cbb071abdfe..e8bab3c1e33 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -238,24 +238,12 @@ else if ( glyph_index >= cff->num_glyphs ) return FT_THROW( Invalid_Argument ); - if ( load_flags & FT_LOAD_NO_RECURSE ) - load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; - - glyph->x_scale = 0x10000L; - glyph->y_scale = 0x10000L; - if ( size ) - { - glyph->x_scale = size->root.metrics.x_scale; - glyph->y_scale = size->root.metrics.y_scale; - } - #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* try to load embedded bitmap if any */ /* */ /* XXX: The convention should be emphasized in */ /* the documents because it can be confusing. */ - if ( size ) { CFF_Face cff_face = (CFF_Face)size->root.face; SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; @@ -284,9 +272,6 @@ FT_Short dummy; - glyph->root.outline.n_points = 0; - glyph->root.outline.n_contours = 0; - glyph->root.metrics.width = (FT_Pos)metrics.width * 64; glyph->root.metrics.height = (FT_Pos)metrics.height * 64; @@ -423,6 +408,25 @@ #endif /* FT_CONFIG_OPTION_SVG */ + /* top-level code ensures that FT_LOAD_NO_HINTING is set */ + /* if FT_LOAD_NO_SCALE is active */ + hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); + + glyph->hint = hinting; + glyph->scaled = scaled; + + if ( scaled ) + { + glyph->x_scale = size->root.metrics.x_scale; + glyph->y_scale = size->root.metrics.y_scale; + } + else + { + glyph->x_scale = 0x10000L; + glyph->y_scale = 0x10000L; + } + /* if we have a CID subfont, use its matrix (which has already */ /* been multiplied with the root matrix) */ @@ -457,18 +461,6 @@ font_offset = cff->top_font.font_dict.font_offset; } - glyph->root.outline.n_points = 0; - glyph->root.outline.n_contours = 0; - - /* top-level code ensures that FT_LOAD_NO_HINTING is set */ - /* if FT_LOAD_NO_SCALE is active */ - hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); - scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); - - glyph->hint = hinting; - glyph->scaled = scaled; - glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ - { #ifdef CFF_CONFIG_OPTION_OLD_ENGINE PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); @@ -602,10 +594,8 @@ { /* Now, set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ - /* bearing the yMax. */ - - /* For composite glyphs, return only left side bearing and */ - /* advance width. */ + /* bearing the yMax. For composite glyphs, return only */ + /* left side bearing and advance width. */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = glyph->root.internal; @@ -624,6 +614,12 @@ FT_Bool has_vertical_info; + glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; + + glyph->root.outline.flags = FT_OUTLINE_REVERSE_FILL; + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; + if ( face->horizontal.number_Of_HMetrics ) { FT_Short horiBearingX = 0; @@ -677,14 +673,6 @@ glyph->root.linearVertAdvance = metrics->vertAdvance; - glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; - - glyph->root.outline.flags = 0; - if ( size && size->root.metrics.y_ppem < 24 ) - glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; - - glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; - /* apply the font matrix, if any */ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || font_matrix.xy != 0 || font_matrix.yx != 0 ) @@ -707,7 +695,7 @@ metrics->vertAdvance += font_offset.y; } - if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) + if ( scaled || force_scaling ) { /* scale the outline and the metrics */ FT_Int n; diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h index 346d4b11c31..662bb7cff53 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c index 979fd45f6ca..326f885056f 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c @@ -4,7 +4,7 @@ * * OpenType and CFF data/program tables loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -442,7 +442,7 @@ if ( cur_offset != 0 ) { FT_TRACE0(( "cff_index_get_pointers:" - " invalid first offset value %ld set to zero\n", + " invalid first offset value %lu set to zero\n", cur_offset )); cur_offset = 0; } @@ -559,8 +559,8 @@ idx->data_offset > stream->size - off2 + 1 ) { FT_ERROR(( "cff_index_access_element:" - " offset to next entry (%ld)" - " exceeds the end of stream (%ld)\n", + " offset to next entry (%lu)" + " exceeds the end of stream (%lu)\n", off2, stream->size - idx->data_offset + 1 )); off2 = stream->size - idx->data_offset + 1; } @@ -982,7 +982,7 @@ if ( glyph_sid > 0xFFFFL - nleft ) { FT_ERROR(( "cff_charset_load: invalid SID range trimmed" - " nleft=%d -> %ld\n", nleft, 0xFFFFL - glyph_sid )); + " nleft=%u -> %ld\n", nleft, 0xFFFFL - glyph_sid )); nleft = ( FT_UInt )( 0xFFFFL - glyph_sid ); } @@ -1315,7 +1315,7 @@ if ( numOperands > count ) { - FT_TRACE4(( " cff_blend_doBlend: Stack underflow %d argument%s\n", + FT_TRACE4(( " cff_blend_doBlend: Stack underflow %u argument%s\n", count, count == 1 ? "" : "s" )); @@ -1466,7 +1466,7 @@ if ( master == 0 ) { blend->BV[master] = FT_FIXED_ONE; - FT_TRACE4(( " build blend vector len %d\n", len )); + FT_TRACE4(( " build blend vector len %u\n", len )); FT_TRACE4(( " [ %f ", blend->BV[master] / 65536.0 )); continue; } @@ -2341,7 +2341,7 @@ if ( face_index > 0 && subfont_index >= font->name_index.count ) { FT_ERROR(( "cff_font_load:" - " invalid subfont index for pure CFF font (%d)\n", + " invalid subfont index for pure CFF font (%u)\n", subfont_index )); error = FT_THROW( Invalid_Argument ); goto Exit; diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h index 02209245421..fdc132c8f3f 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h @@ -4,7 +4,7 @@ * * OpenType & CFF data/program tables loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c index 7c6713739a1..1aeb908f4a1 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c @@ -4,7 +4,7 @@ * * OpenType objects manager (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -537,8 +537,8 @@ sfnt_format = 1; - /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ - /* font; in the latter case it doesn't have a `head' table */ + /* the font may be OpenType/CFF, SVG CEF, or sfnt/CFF; a `head' table */ + /* implies OpenType/CFF, otherwise just look for an optional cmap */ error = face->goto_table( face, TTAG_head, stream, 0 ); if ( !error ) { @@ -554,7 +554,9 @@ { /* load the `cmap' table explicitly */ error = sfnt->load_cmap( face, stream ); - if ( error ) + + /* this may fail because CID-keyed fonts don't have a cmap */ + if ( FT_ERR_NEQ( error, Table_Missing ) && FT_ERR_NEQ( error, Ok ) ) goto Exit; } @@ -651,7 +653,7 @@ { s = cff_index_get_sid_string( cff, idx ); if ( s ) - FT_TRACE4(( " %5d %s\n", idx, s )); + FT_TRACE4(( " %5u %s\n", idx, s )); } /* In Multiple Master CFFs, two SIDs hold the Normalize Design */ @@ -666,7 +668,7 @@ FT_PtrDist l; - FT_TRACE4(( " %5d ", idx + 390 )); + FT_TRACE4(( " %5u ", idx + 390 )); for ( l = 0; l < s1len; l++ ) FT_TRACE4(( "%c", s1[l] )); FT_TRACE4(( "\n" )); @@ -681,7 +683,7 @@ FT_PtrDist l; - FT_TRACE4(( " %5d ", cff->num_strings + 390 )); + FT_TRACE4(( " %5u ", cff->num_strings + 390 )); for ( l = 0; l < s1len; l++ ) FT_TRACE4(( "%c", s1[l] )); FT_TRACE4(( "\n" )); diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h index 91ad83b1cd0..982dcd64dd0 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h @@ -4,7 +4,7 @@ * * OpenType objects manager (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c index 92a69c3b516..864b2490b3b 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c @@ -4,7 +4,7 @@ * * CFF token stream parser (body) * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -892,7 +892,7 @@ dict->cid_supplement )); error = FT_Err_Ok; - FT_TRACE4(( " %d %d %ld\n", + FT_TRACE4(( " %u %u %ld\n", dict->cid_registry, dict->cid_ordering, dict->cid_supplement )); @@ -929,7 +929,7 @@ priv->vsindex = (FT_UInt)cff_parse_num( parser, data++ ); - FT_TRACE4(( " %d\n", priv->vsindex )); + FT_TRACE4(( " %u\n", priv->vsindex )); error = FT_Err_Ok; @@ -979,7 +979,7 @@ goto Exit; } - FT_TRACE4(( " %d value%s blended\n", + FT_TRACE4(( " %u value%s blended\n", numBlends, numBlends == 1 ? "" : "s" )); @@ -1014,7 +1014,7 @@ if ( dict->maxstack < CFF2_DEFAULT_STACK ) dict->maxstack = CFF2_DEFAULT_STACK; - FT_TRACE4(( " %d\n", dict->maxstack )); + FT_TRACE4(( " %u\n", dict->maxstack )); Exit: return error; diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h index ca6b18af6aa..47cceb1a4a0 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h @@ -4,7 +4,7 @@ * * CFF token stream parser (specification) * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h index da45faa7f4e..cc5aaa2867a 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h @@ -4,7 +4,7 @@ * * CFF token definitions (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h index c439a8c4a0b..1591979d370 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h @@ -4,7 +4,7 @@ * * CID error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c index 7b571322d45..249ede5757d 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 Glyph Loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -103,20 +103,20 @@ if ( ( cid->fd_bytes == 1 && fd_select == 0xFFU ) || ( cid->fd_bytes == 2 && fd_select == 0xFFFFU ) ) { - FT_TRACE1(( "cid_load_glyph: fail for glyph index %d:\n", + FT_TRACE1(( "cid_load_glyph: fail for glyph index %u:\n", glyph_index )); - FT_TRACE1(( " FD number %ld is the maximum\n", + FT_TRACE1(( " FD number %lu is the maximum\n", fd_select )); - FT_TRACE1(( " integer fitting into %d byte%s\n", + FT_TRACE1(( " integer fitting into %u byte%s\n", cid->fd_bytes, cid->fd_bytes == 1 ? "" : "s" )); } else { - FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + FT_TRACE0(( "cid_load_glyph: fail for glyph index %u:\n", glyph_index )); - FT_TRACE0(( " FD number %ld is larger\n", + FT_TRACE0(( " FD number %lu is larger\n", fd_select )); - FT_TRACE0(( " than number of dictionaries (%d)\n", + FT_TRACE0(( " than number of dictionaries (%u)\n", cid->num_dicts )); } @@ -125,7 +125,7 @@ } else if ( off2 > stream->size ) { - FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + FT_TRACE0(( "cid_load_glyph: fail for glyph index %u:\n", glyph_index )); FT_TRACE0(( " end of the glyph data\n" )); FT_TRACE0(( " is beyond the data stream\n" )); @@ -135,7 +135,7 @@ } else if ( off1 > off2 ) { - FT_TRACE0(( "cid_load_glyph: fail for glyph index %d:\n", + FT_TRACE0(( "cid_load_glyph: fail for glyph index %u:\n", glyph_index )); FT_TRACE0(( " the end position of glyph data\n" )); FT_TRACE0(( " is set before the start position\n" )); @@ -252,8 +252,8 @@ cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; if ( cs_offset > glyph_length ) { - FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, " - "offset to the charstring is beyond glyph length\n", + FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%u," + " offset to the charstring is beyond glyph length\n", glyph_index )); error = FT_THROW( Invalid_Offset ); goto Exit; @@ -452,16 +452,12 @@ glyph->x_scale = cidsize->metrics.x_scale; glyph->y_scale = cidsize->metrics.y_scale; - cidglyph->outline.n_points = 0; - cidglyph->outline.n_contours = 0; - hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); glyph->hint = hinting; glyph->scaled = scaled; - cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; error = psaux->t1_decoder_funcs->init( &decoder, cidglyph->face, @@ -501,12 +497,8 @@ /* now set the metrics -- this is rather simple, as */ /* the left side bearing is the xMin, and the top side */ - /* bearing the yMax */ - cidglyph->outline.flags &= FT_OUTLINE_OWNER; - cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; - - /* for composite glyphs, return only left side bearing and */ - /* advance width */ + /* bearing the yMax; for composite glyphs, return only */ + /* left side bearing and advance width */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = cidglyph->internal; @@ -527,6 +519,13 @@ FT_Glyph_Metrics* metrics = &cidglyph->metrics; + cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; + + cidglyph->outline.flags &= FT_OUTLINE_OWNER; + cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; + if ( cidsize->metrics.y_ppem < 24 ) + cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; + /* copy the _unscaled_ advance width */ metrics->horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); @@ -539,11 +538,6 @@ face->cid.font_bbox.yMin ) >> 16; cidglyph->linearVertAdvance = metrics->vertAdvance; - cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; - - if ( cidsize->metrics.y_ppem < 24 ) - cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - /* apply the font matrix, if any */ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || font_matrix.xy != 0 || font_matrix.yx != 0 ) diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h index 9fdc9db5892..cef96073ded 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h @@ -4,7 +4,7 @@ * * OpenType Glyph Loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c index 722f5a34ddf..bb1bf13e221 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h index 7f030b32df7..659dd0e378c 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 font loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c index 8d337c41128..634bbf2f135 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c @@ -4,7 +4,7 @@ * * CID objects manager (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h index d371cbe9954..800268efa2f 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h @@ -4,7 +4,7 @@ * * CID objects manager (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c index 73a3ade893b..4d1ba335960 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h index 0f5baddcb92..6ae2e542394 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h @@ -4,7 +4,7 @@ * * CID-keyed Type1 parser (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c index 4be8a5c00d5..a3a587c57bf 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c @@ -4,7 +4,7 @@ * * CID driver interface (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h index 7ddce431c5b..55d0b8a0d9b 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h @@ -4,7 +4,7 @@ * * High-level CID driver interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h index 160897d1447..25ba74fed94 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h @@ -4,7 +4,7 @@ * * CID token definitions (specification only). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c index e2f6a8e5adb..b813efde4eb 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c @@ -4,7 +4,7 @@ * * AFM parser (body). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h index b7766372821..add8597717d 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h @@ -4,7 +4,7 @@ * * AFM parser (specification). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c index 9556e11a586..17bdd23c7d4 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (body). * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -2141,7 +2141,7 @@ decoder->locals_bias ); - FT_TRACE4(( " callsubr (idx %d, entering level %td)\n", + FT_TRACE4(( " callsubr (idx %u, entering level %td)\n", idx, zone - decoder->zones + 1 )); @@ -2185,7 +2185,7 @@ decoder->globals_bias ); - FT_TRACE4(( " callgsubr (idx %d, entering level %td)\n", + FT_TRACE4(( " callgsubr (idx %u, entering level %td)\n", idx, zone - decoder->zones + 1 )); diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h index 038f7235c3d..e72ec043baa 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h @@ -4,7 +4,7 @@ * * PostScript CFF (Type 2) decoding routines (specification). * - * Copyright (C) 2017-2024 by + * Copyright (C) 2017-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h index 18428c40d5a..0d7fe2b6121 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h @@ -4,7 +4,7 @@ * * PS auxiliary module error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c index 6826f9d8d3e..942804190c5 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (body). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h index 82d7e348af8..4a5ebc1b607 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h @@ -4,7 +4,7 @@ * * FreeType auxiliary PostScript module implementation (specification). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -46,9 +46,6 @@ FT_BEGIN_HEADER const CFF_Decoder_FuncsRec cff_decoder_funcs; - FT_EXPORT_VAR( const FT_Module_Class ) psaux_driver_class; - - FT_DECLARE_MODULE( psaux_module_class ) diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c index 56c0ecd1d7f..4567d3f3c06 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c @@ -4,7 +4,7 @@ * * Some convenience conversions (body). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h index 91fcd15a1c9..63735af411f 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h @@ -4,7 +4,7 @@ * * Some convenience conversions (specification). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c index 7572e225e37..7e3475e6f58 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c @@ -618,7 +618,7 @@ /* Our copy of it does not change that requirement. */ cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 ); - charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack ); + charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack ); /* catch errors so far */ if ( *error ) diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c index eca465f009e..8159fd6ef15 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -460,6 +460,9 @@ case '%': skip_comment( &cur, limit ); break; + + default: + break; } } @@ -1145,7 +1148,7 @@ FT_ERROR(( "ps_parser_load_field:" " expected a name or string\n" )); FT_ERROR(( " " - " but found token of type %d instead\n", + " but found token of type %u instead\n", token.type )); error = FT_THROW( Invalid_File_Format ); goto Exit; @@ -1225,7 +1228,7 @@ if ( result < 0 || (FT_UInt)result < max_objects ) { FT_ERROR(( "ps_parser_load_field:" - " expected %d integer%s in the %s subarray\n", + " expected %u integer%s in the %s subarray\n", max_objects, max_objects > 1 ? "s" : "", i == 0 ? "first" : ( i == 1 ? "second" diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h index 345fc8a7335..277aa1247c5 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h @@ -4,7 +4,7 @@ * * Auxiliary functions for PostScript fonts (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c index 5681c3bd0fd..66493b68123 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c @@ -4,7 +4,7 @@ * * Type 1 character map support (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h index 445e6a2784f..114bfbb0410 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h @@ -4,7 +4,7 @@ * * Type 1 character map support (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c index c74baa8038f..c3fb343d4c9 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (body). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -1633,7 +1633,7 @@ default: FT_ERROR(( "t1_decoder_parse_charstrings:" - " unhandled opcode %d\n", op )); + " unhandled opcode %u\n", op )); goto Syntax_Error; } diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h index 16203b8f734..7b913f55dff 100644 --- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h +++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h @@ -4,7 +4,7 @@ * * PostScript Type 1 decoding routines (specification). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c index 967767b3485..ca30702321d 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (body). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used @@ -100,7 +100,7 @@ if ( idx >= table->max_hints ) { - FT_TRACE0(( "psh_hint_table_record: invalid hint index %d\n", idx )); + FT_TRACE0(( "psh_hint_table_record: invalid hint index %u\n", idx )); return; } diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h index fb362f061b6..f4aa8540559 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h @@ -4,7 +4,7 @@ * * PostScript hinting algorithm (specification). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c index 435f45838ff..521a5ff6c5c 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c @@ -5,7 +5,7 @@ * PostScript hinter global hinting management (body). * Inspired by the new auto-hinter module. * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h index c5a5c913168..555e99facb2 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h @@ -4,7 +4,7 @@ * * PostScript hinter global hinting management. * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c index 9965d5b16bf..c9f4a94fe98 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c @@ -4,7 +4,7 @@ * * FreeType PostScript hinter module implementation (body). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h index 62ac0a60fdc..de9c398e9fb 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h @@ -4,7 +4,7 @@ * * PostScript hinter module interface (specification). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h index e9641340e53..7076664ddde 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h @@ -4,7 +4,7 @@ * * PS Hinter error codes (specification only). * - * Copyright (C) 2003-2024 by + * Copyright (C) 2003-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c index 0b2b549fc29..13754313fbb 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c @@ -4,7 +4,7 @@ * * FreeType PostScript hints recorder (body). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -467,7 +467,7 @@ table->num_masks--; } else - FT_TRACE0(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n", + FT_TRACE0(( "ps_mask_table_merge: ignoring invalid indices (%u,%u)\n", index1, index2 )); Exit: @@ -817,7 +817,7 @@ /* limit "dimension" to 0..1 */ if ( dimension > 1 ) { - FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n", + FT_TRACE0(( "ps_hints_stem: invalid dimension (%u) used\n", dimension )); dimension = ( dimension != 0 ); } @@ -870,7 +870,7 @@ /* limit "dimension" to 0..1 */ if ( dimension > 1 ) { - FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n", + FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%u) used\n", dimension )); dimension = ( dimension != 0 ); } @@ -976,7 +976,7 @@ if ( bit_count != count1 + count2 ) { FT_TRACE0(( "ps_hints_t2mask:" - " called with invalid bitcount %d (instead of %d)\n", + " called with invalid bitcount %u (instead of %u)\n", bit_count, count1 + count2 )); /* simply ignore the operator */ @@ -1022,7 +1022,7 @@ if ( bit_count != count1 + count2 ) { FT_TRACE0(( "ps_hints_t2counter:" - " called with invalid bitcount %d (instead of %d)\n", + " called with invalid bitcount %u (instead of %u)\n", bit_count, count1 + count2 )); /* simply ignore the operator */ diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h index 7e375af7ba8..a79069f98d2 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h @@ -4,7 +4,7 @@ * * Postscript (Type1/Type2) hints recorder (specification). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c index 35d054d1cfb..c5d71edad88 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c @@ -4,7 +4,7 @@ * * psnames module implementation (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h index 770458316b1..482fd0a36d1 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h @@ -4,7 +4,7 @@ * * High-level psnames module interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h index e123eb65e39..17987f9cd4f 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h +++ b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h @@ -4,7 +4,7 @@ * * PS names module error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h index 2a941b04609..65ce6c0b47f 100644 --- a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h +++ b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h @@ -4,7 +4,7 @@ * * PostScript glyph names. * - * Copyright (C) 2005-2024 by + * Copyright (C) 2005-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h index 943f2aa0a50..9d97223e94e 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h @@ -5,7 +5,7 @@ * Miscellaneous macros for stand-alone rasterizer (specification * only). * - * Copyright (C) 2005-2024 by + * Copyright (C) 2005-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c index e4b7b937d5a..807d444e7aa 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -251,7 +251,11 @@ /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */ /* for clipping computations. It simply uses the FT_MulDiv() function */ /* defined in `ftcalc.h'. */ -#define SMulDiv_No_Round FT_MulDiv_No_Round +#ifdef FT_INT64 +#define SMulDiv( a, b, c ) (Long)( (FT_Int64)(a) * (b) / (c) ) +#else +#define SMulDiv FT_MulDiv_No_Round +#endif /* The rasterizer is a very general purpose component; please leave */ /* the following redefinitions there (you never know your target */ @@ -653,7 +657,7 @@ ras.cProfile->height = 0; } - ras.cProfile->flags = ras.dropOutControl; + ras.cProfile->flags = ras.dropOutControl; switch ( aState ) { @@ -967,14 +971,14 @@ goto Fin; } - Ix = SMulDiv_No_Round( e - y1, Dx, Dy ); + Ix = SMulDiv( e - y1, Dx, Dy ); x1 += Ix; *top++ = x1; if ( --size ) { Ax = Dx * ( e - y1 ) - Dy * Ix; /* remainder */ - Ix = FMulDiv( ras.precision, Dx, Dy ); + Ix = SMulDiv( ras.precision, Dx, Dy ); Rx = Dx * ras.precision - Dy * Ix; /* remainder */ Dx = 1; @@ -1090,8 +1094,8 @@ PLong top; - y1 = arc[degree].y; - y2 = arc[0].y; + y1 = arc[degree].y; + y2 = arc[0].y; if ( y2 < miny || y1 > maxy ) return SUCCESS; diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h index ad9cb1b9fe0..64499bf955b 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c index fd9f174f2e1..3fa008704e5 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h index cf3e73c0a24..d838a942b04 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h @@ -4,7 +4,7 @@ * * The FreeType glyph rasterizer interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h index 326d42e0438..39d82a8051a 100644 --- a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h +++ b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h @@ -4,7 +4,7 @@ * * monochrome renderer error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c index 76181568af9..9df75dc3acc 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h index 6e7a5c08e71..c59199e60df 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h @@ -4,7 +4,7 @@ * * PNG Bitmap glyph support. * - * Copyright (C) 2013-2024 by + * Copyright (C) 2013-2025 by * Google, Inc. * Written by Stuart Gill and Behdad Esfahbod. * diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c index 81072207b49..ec78247aa56 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -895,7 +895,7 @@ FT_TRACE0(( "sfnt_get_var_ps_name:" " Shortening variation PS name prefix\n" )); FT_TRACE0(( " " - " to %d characters\n", len )); + " to %u characters\n", len )); } face->var_postscript_prefix = result; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h index 6f71489fdc1..be4e33166c1 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h @@ -4,7 +4,7 @@ * * High-level SFNT driver interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h index d3ca1d9aa8b..2da4ac776b0 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h @@ -4,7 +4,7 @@ * * SFNT error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c index 6ee4e5e939b..6af35787e85 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c @@ -4,7 +4,7 @@ * * SFNT object management (base). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -579,6 +579,9 @@ if ( face_instance_index < 0 && face_index > 0 ) face_index--; + /* Note that `face_index` is also used to enumerate elements */ + /* of containers like a Mac Resource; this means we must */ + /* check whether we actually have a TTC. */ if ( face_index >= face->ttc_header.count ) { if ( face_instance_index >= 0 ) @@ -1127,9 +1130,9 @@ flags |= FT_FACE_FLAG_VERTICAL; /* kerning available ? */ - if ( TT_FACE_HAS_KERNING( face ) + if ( face->kern_avail_bits #ifdef TT_CONFIG_OPTION_GPOS_KERNING - || face->gpos_kerning_available + || face->num_gpos_lookups_kerning #endif ) flags |= FT_FACE_FLAG_KERNING; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h index 90847d95732..8c38b727950 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h @@ -4,7 +4,7 @@ * * SFNT object management (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c index 14514bf9574..015c7b78b4d 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c @@ -4,7 +4,7 @@ * * WOFF format management (base). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h index a04735ffe28..df7ace5c209 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h @@ -4,7 +4,7 @@ * * WOFFF format management (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c index 589b3e0c6b7..5acbbaa2a77 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c @@ -4,7 +4,7 @@ * * WOFF2 format management (base). * - * Copyright (C) 2019-2024 by + * Copyright (C) 2019-2025 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -902,7 +902,7 @@ substreams[i].offset = pos + offset; substreams[i].size = substream_size; - FT_TRACE5(( " Substream %d: offset = %lu; size = %lu;\n", + FT_TRACE5(( " Substream %u: offset = %lu; size = %lu;\n", i, substreams[i].offset, substreams[i].size )); offset += substream_size; } @@ -1592,7 +1592,7 @@ WOFF2_TableRec table = *( indices[nn] ); - FT_TRACE3(( "Seeking to %ld with table size %ld.\n", + FT_TRACE3(( "Seeking to %lu with table size %lu.\n", table.src_offset, table.src_length )); FT_TRACE3(( "Table tag: %c%c%c%c.\n", (FT_Char)( table.Tag >> 24 ), @@ -1943,7 +1943,7 @@ src_offset += table->TransformLength; table->dst_offset = 0; - FT_TRACE2(( " %c%c%c%c %08d %08d %08ld %08ld %08ld\n", + FT_TRACE2(( " %c%c%c%c %08d %08d %08lu %08lu %08lu\n", (FT_Char)( table->Tag >> 24 ), (FT_Char)( table->Tag >> 16 ), (FT_Char)( table->Tag >> 8 ), diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h index f41140648dc..588761d0c8e 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h @@ -4,7 +4,7 @@ * * WOFFF2 format management (specification). * - * Copyright (C) 2019-2024 by + * Copyright (C) 2019-2025 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c index 28f4d1173c0..91b02344224 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (body). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -179,7 +179,7 @@ cmap_info->format = 0; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + cmap_info->language = TT_PEEK_USHORT( p ); return FT_Err_Ok; } @@ -596,7 +596,7 @@ cmap_info->format = 2; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + cmap_info->language = TT_PEEK_USHORT( p ); return FT_Err_Ok; } @@ -1539,7 +1539,7 @@ cmap_info->format = 4; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + cmap_info->language = TT_PEEK_USHORT( p ); return FT_Err_Ok; } @@ -1712,7 +1712,7 @@ cmap_info->format = 6; - cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + cmap_info->language = TT_PEEK_USHORT( p ); return FT_Err_Ok; } @@ -2009,7 +2009,7 @@ cmap_info->format = 8; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); + cmap_info->language = TT_PEEK_ULONG( p ); return FT_Err_Ok; } @@ -2184,7 +2184,7 @@ cmap_info->format = 10; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); + cmap_info->language = TT_PEEK_ULONG( p ); return FT_Err_Ok; } @@ -2528,7 +2528,7 @@ cmap_info->format = 12; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); + cmap_info->language = TT_PEEK_ULONG( p ); return FT_Err_Ok; } @@ -2844,7 +2844,7 @@ cmap_info->format = 13; - cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); + cmap_info->language = TT_PEEK_ULONG( p ); return FT_Err_Ok; } @@ -3792,7 +3792,7 @@ return FT_THROW( Invalid_Table ); /* Version 1.8.3 of the OpenType specification contains the following */ - /* (https://docs.microsoft.com/en-us/typography/opentype/spec/cmap): */ + /* (https://learn.microsoft.com/typography/opentype/spec/cmap): */ /* */ /* The 'cmap' table version number remains at 0x0000 for fonts that */ /* make use of the newer subtable formats. */ @@ -3803,7 +3803,7 @@ p += 2; num_cmaps = TT_NEXT_USHORT( p ); - FT_TRACE4(( "tt_face_build_cmaps: %d cmaps\n", num_cmaps )); + FT_TRACE4(( "tt_face_build_cmaps: %u cmaps\n", num_cmaps )); limit = table + face->cmap_size; for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h index e2c5e72bf02..645e9e37e0c 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h @@ -4,7 +4,7 @@ * * TrueType character mapping table (cmap) support (specification). * - * Copyright (C) 2002-2024 by + * Copyright (C) 2002-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h index 370898363f3..65807bb7378 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h @@ -4,7 +4,7 @@ * * TT CMAP classes definitions (specification only). * - * Copyright (C) 2009-2024 by + * Copyright (C) 2009-2025 by * Oran Agra and Mickey Gabel. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c index b37658dde9e..ad9ad6f2710 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (body). * - * Copyright (C) 2018-2024 by + * Copyright (C) 2018-2025 by * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. * * Originally written by Shao Yu Zhang . @@ -51,7 +51,7 @@ #define COLOR_STOP_SIZE 6U #define VAR_IDX_BASE_SIZE 4U #define LAYER_SIZE 4U -/* https://docs.microsoft.com/en-us/typography/opentype/spec/colr#colr-header */ +/* https://learn.microsoft.com/typography/opentype/spec/colr#colr-header */ /* 3 * uint16 + 2 * Offset32 */ #define COLRV0_HEADER_SIZE 14U /* COLRV0_HEADER_SIZE + 5 * Offset32 */ diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h index 30031464c73..3913acc74d5 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h @@ -4,7 +4,7 @@ * * TrueType and OpenType colored glyph layer support (specification). * - * Copyright (C) 2018-2024 by + * Copyright (C) 2018-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang . diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c index 997eb869ffc..6d1208f6af2 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (body). * - * Copyright (C) 2018-2024 by + * Copyright (C) 2018-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang . diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h index bb301ae88b6..a0b4c9d927f 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h @@ -4,7 +4,7 @@ * * TrueType and OpenType color palette support (specification). * - * Copyright (C) 2018-2024 by + * Copyright (C) 2018-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Originally written by Shao Yu Zhang . diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c index f0411366af4..76618b0d3bb 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c @@ -2,10 +2,9 @@ * * ttkern.c * - * Load the basic TrueType kerning table. This doesn't handle - * kerning data within the GPOS table at the moment. + * Routines to parse and access the 'kern' table for kerning (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h index a54e51df12d..e0075dce61d 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h @@ -2,10 +2,10 @@ * * ttkern.h * - * Load the basic TrueType kerning table. This doesn't handle - * kerning data within the GPOS table at the moment. + * Routines to parse and access the 'kern' table for kerning + * (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -40,8 +40,6 @@ FT_BEGIN_HEADER FT_UInt left_glyph, FT_UInt right_glyph ); -#define TT_FACE_HAS_KERNING( face ) ( (face)->kern_avail_bits != 0 ) - FT_END_HEADER diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c index c3a5fae2cb9..0c257ce4d31 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -535,7 +535,8 @@ * The tag of table to load. Use the value 0 if you want * to access the whole font file, else set this parameter * to a valid TrueType table tag that you can forge with - * the MAKE_TT_TAG macro. + * the MAKE_TT_TAG macro. Use value 1 to access the table + * directory. * * offset :: * The starting offset in the table (or the file if @@ -577,7 +578,29 @@ FT_ULong size; - if ( tag != 0 ) + if ( tag == 0 ) + { + /* The whole font file. */ + size = face->root.stream->size; + } + else if ( tag == 1 ) + { + /* The currently selected font's table directory. */ + /* */ + /* Note that `face_index` is also used to enumerate elements */ + /* of containers like a Mac Resource; this means we must */ + /* check whether we actually have a TTC (with multiple table */ + /* directories). */ + FT_Long idx = face->root.face_index & 0xFFFF; + + + if ( idx >= face->ttc_header.count ) + idx = 0; + + offset += face->ttc_header.offsets[idx]; + size = 4 + 8 + 16 * face->num_tables; + } + else { /* look for tag in font directory */ table = tt_face_lookup_table( face, tag ); @@ -590,9 +613,6 @@ offset += table->Offset; size = table->Length; } - else - /* tag == 0 -- the user wants to access the font file directly */ - size = face->root.stream->size; if ( length && *length == 0 ) { diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h index 2b1d62d9bd9..e3666c901b1 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h @@ -5,7 +5,7 @@ * Load the basic TrueType tables, i.e., tables that can be either in * TTF or OTF fonts (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c index 27884118563..541d8447470 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (body). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -306,7 +306,7 @@ } #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( var && face->blend ) + if ( var && FT_IS_VARIATION( &face->root ) ) { FT_Face f = FT_FACE( face ); FT_Int a = (FT_Int)*aadvance; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h index 34b3c0e18f2..1ee84507f15 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h @@ -4,7 +4,7 @@ * * Load the metrics tables common to TTF and OTF fonts (specification). * - * Copyright (C) 2006-2024 by + * Copyright (C) 2006-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c index 5698a62c8d1..4246b6c8eff 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h index 150db6c3981..a11b6696854 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h @@ -5,7 +5,7 @@ * PostScript name table processing for TrueType and OpenType fonts * (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c index cb3a8abf182..9f9013bf39b 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (body). * - * Copyright (C) 2005-2024 by + * Copyright (C) 2005-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Copyright 2013 by Google, Inc. @@ -342,7 +342,7 @@ FT_TRACE2(( "tt_face_load_strike_metrics:" " sanitizing invalid ascender and descender\n" )); FT_TRACE2(( " " - " values for strike %ld (%dppem, %dppem)\n", + " values for strike %lu (%dppem, %dppem)\n", strike_index, metrics->x_ppem, metrics->y_ppem )); @@ -993,7 +993,7 @@ goto Fail; } - FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d component%s\n", + FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %u component%s\n", num_components, num_components == 1 ? "" : "s" )); @@ -1419,7 +1419,7 @@ image_start = image_offset + image_start; FT_TRACE3(( "tt_sbit_decoder_load_image:" - " found sbit (format %d) for glyph index %d\n", + " found sbit (format %u) for glyph index %u\n", image_format, glyph_index )); return tt_sbit_decoder_load_bitmap( decoder, @@ -1438,13 +1438,13 @@ if ( recurse_count ) { FT_TRACE4(( "tt_sbit_decoder_load_image:" - " missing subglyph sbit with glyph index %d\n", + " missing subglyph sbit with glyph index %u\n", glyph_index )); return FT_THROW( Invalid_Composite ); } FT_TRACE4(( "tt_sbit_decoder_load_image:" - " no sbit found for glyph index %d\n", glyph_index )); + " no sbit found for glyph index %u\n", glyph_index )); return FT_THROW( Missing_Bitmap ); } @@ -1462,12 +1462,13 @@ FT_Int originOffsetX, originOffsetY; FT_Tag graphicType; FT_Int recurse_depth = 0; + FT_Bool flipped = FALSE; FT_Error error; FT_Byte* p; - FT_UNUSED( map ); #ifndef FT_CONFIG_OPTION_USE_PNG + FT_UNUSED( map ); FT_UNUSED( metrics_only ); #endif @@ -1517,12 +1518,16 @@ switch ( graphicType ) { + case FT_MAKE_TAG( 'f', 'l', 'i', 'p' ): + flipped = !flipped; + FALL_THROUGH; + case FT_MAKE_TAG( 'd', 'u', 'p', 'e' ): - if ( recurse_depth < 4 ) + if ( recurse_depth++ < 4 ) { glyph_index = FT_GET_USHORT(); FT_FRAME_EXIT(); - recurse_depth++; + goto retry; } error = FT_THROW( Invalid_File_Format ); @@ -1540,6 +1545,38 @@ glyph_end - glyph_start - 8, TRUE, metrics_only ); + if ( flipped && !metrics_only && !error ) + { + FT_UInt32* curr_pos = (FT_UInt32*)map->buffer; + + /* `Load_SBit_Png` always returns a pixmap with 32 bits per pixel */ + /* and no extra pitch bytes. */ + FT_UInt width = map->width; + FT_UInt y; + + + for ( y = 0; y < map->rows; y++ ) + { + FT_UInt32* left = curr_pos; + FT_UInt32* right = curr_pos + width - 1; + + + while ( left < right ) + { + FT_UInt32 value; + + + value = *right; + *right = *left; + *left = value; + + left++; + right--; + } + + curr_pos += width; + } + } #else error = FT_THROW( Unimplemented_Feature ); #endif diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h index 96f80a58424..7427149d68f 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h @@ -4,7 +4,7 @@ * * TrueType and OpenType embedded bitmap support (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c index 532ccfa1737..0f9e3889aab 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (base). * - * Copyright (C) 2019-2024 by + * Copyright (C) 2019-2025 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h index d03b4b41bc9..e223022962e 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h @@ -4,7 +4,7 @@ * * WOFF2 Font table tags (specification). * - * Copyright (C) 2019-2024 by + * Copyright (C) 2019-2025 by * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c index b7c0632a6fa..365fbad42ad 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c @@ -4,7 +4,7 @@ * * A new `perfect' anti-aliasing renderer (body). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -157,10 +157,6 @@ #define ft_memset memset -#define ft_setjmp setjmp -#define ft_longjmp longjmp -#define ft_jmp_buf jmp_buf - typedef ptrdiff_t FT_PtrDist; @@ -170,8 +166,8 @@ typedef ptrdiff_t FT_PtrDist; #define Smooth_Err_Invalid_Argument -3 #define Smooth_Err_Raster_Overflow -4 -#define FT_BEGIN_HEADER -#define FT_END_HEADER +#define FT_BEGIN_HEADER /* nothing */ +#define FT_END_HEADER /* nothing */ #include "ftimage.h" #include "ftgrays.h" @@ -495,6 +491,7 @@ typedef ptrdiff_t FT_PtrDist; TCoord min_ey, max_ey; TCoord count_ey; /* same as (max_ey - min_ey) */ + int error; /* pool overflow exception */ PCell cell; /* current cell */ PCell cell_free; /* call allocation next free slot */ PCell cell_null; /* last cell, used as dumpster and limit */ @@ -510,8 +507,6 @@ typedef ptrdiff_t FT_PtrDist; FT_Raster_Span_Func render_span; void* render_span_data; - ft_jmp_buf jump_buffer; - } gray_TWorker, *gray_PWorker; #if defined( _MSC_VER ) @@ -613,9 +608,14 @@ typedef ptrdiff_t FT_PtrDist; } /* insert new cell */ - cell = ras.cell_free++; - if ( cell >= ras.cell_null ) - ft_longjmp( ras.jump_buffer, 1 ); + cell = ras.cell_free; + if ( cell == ras.cell_null ) + { + ras.error = FT_THROW( Raster_Overflow ); + goto Found; + } + + ras.cell_free = cell + 1; cell->x = ex; cell->area = 0; @@ -1353,7 +1353,8 @@ typedef ptrdiff_t FT_PtrDist; ras.x = x; ras.y = y; - return 0; + + return ras.error; } @@ -1365,7 +1366,8 @@ typedef ptrdiff_t FT_PtrDist; gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); - return 0; + + return ras.error; } @@ -1378,7 +1380,8 @@ typedef ptrdiff_t FT_PtrDist; gray_render_conic( RAS_VAR_ control, to ); - return 0; + + return ras.error; } @@ -1392,7 +1395,8 @@ typedef ptrdiff_t FT_PtrDist; gray_render_cubic( RAS_VAR_ control1, control2, to ); - return 0; + + return ras.error; } @@ -1700,30 +1704,22 @@ typedef ptrdiff_t FT_PtrDist; gray_convert_glyph_inner( RAS_ARG_ int continued ) { - volatile int error; + int error; - if ( ft_setjmp( ras.jump_buffer ) == 0 ) - { - if ( continued ) - FT_Trace_Disable(); - error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); - if ( continued ) - FT_Trace_Enable(); + if ( continued ) + FT_Trace_Disable(); + error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); + if ( continued ) + FT_Trace_Enable(); - FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n", - ras.min_ey, - ras.max_ey, - ras.cell_null - ras.cell_free, - ras.cell_null - ras.cell_free == 1 ? "" : "s" )); - } - else - { - error = FT_THROW( Raster_Overflow ); - - FT_TRACE7(( "band [%d..%d]: to be bisected\n", - ras.min_ey, ras.max_ey )); - } + FT_TRACE7(( error == Smooth_Err_Raster_Overflow + ? "band [%d..%d]: to be bisected\n" + : "band [%d..%d]: %td cell%s remaining\n", + ras.min_ey, + ras.max_ey, + ras.cell_null - ras.cell_free, + ras.cell_null - ras.cell_free == 1 ? "" : "s" )); return error; } @@ -1873,6 +1869,7 @@ typedef ptrdiff_t FT_PtrDist; TCoord* band; int continued = 0; + int error = Smooth_Err_Ok; /* Initialize the null cell at the end of the poll. */ @@ -1907,7 +1904,6 @@ typedef ptrdiff_t FT_PtrDist; do { TCoord i; - int error; ras.min_ex = band[1]; @@ -1922,6 +1918,7 @@ typedef ptrdiff_t FT_PtrDist; ras.cell_free = buffer + n; ras.cell = ras.cell_null; + ras.error = Smooth_Err_Ok; error = gray_convert_glyph_inner( RAS_VAR_ continued ); continued = 1; @@ -1936,7 +1933,7 @@ typedef ptrdiff_t FT_PtrDist; continue; } else if ( error != Smooth_Err_Raster_Overflow ) - return error; + goto Exit; /* render pool overflow; we will reduce the render band by half */ i = ( band[0] - band[1] ) >> 1; @@ -1945,7 +1942,8 @@ typedef ptrdiff_t FT_PtrDist; if ( i == 0 ) { FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); - return FT_THROW( Raster_Overflow ); + error = FT_THROW( Raster_Overflow ); + goto Exit; } band++; @@ -1954,7 +1952,11 @@ typedef ptrdiff_t FT_PtrDist; } while ( band >= bands ); } - return Smooth_Err_Ok; + Exit: + ras.cell = ras.cell_free = ras.cell_null = NULL; + ras.ycells = NULL; + + return error; } diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h index 940fbe8c79b..e463e5b3eb8 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h @@ -4,7 +4,7 @@ * * FreeType smooth renderer declaration * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -19,11 +19,6 @@ #ifndef FTGRAYS_H_ #define FTGRAYS_H_ -#ifdef __cplusplus - extern "C" { -#endif - - #ifdef STANDALONE_ #include "ftimage.h" #else @@ -31,6 +26,7 @@ #include #endif +FT_BEGIN_HEADER /************************************************************************** * @@ -46,10 +42,7 @@ FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_grays_raster; - -#ifdef __cplusplus - } -#endif +FT_END_HEADER #endif /* FTGRAYS_H_ */ diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h index 6d41fb8e0fd..8d5068549fa 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h @@ -4,7 +4,7 @@ * * smooth renderer error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c index f0acc1ea4a6..21a6eca00ba 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (body). * - * Copyright (C) 2000-2024 by + * Copyright (C) 2000-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h index d7b61a9e60e..f76708ae701 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h @@ -4,7 +4,7 @@ * * Anti-aliasing renderer interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c index 4ab68eb9a12..6369d83d6d5 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c @@ -4,7 +4,7 @@ * * TrueType font driver implementation (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -220,12 +220,12 @@ { /* Use 'kern' table if available since that can be faster; otherwise */ /* use GPOS kerning pairs if available. */ - if ( ttface->kern_avail_bits != 0 ) + if ( ttface->kern_avail_bits ) kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph ); #ifdef TT_CONFIG_OPTION_GPOS_KERNING - else if ( ttface->gpos_kerning_available ) + else if ( ttface->num_gpos_lookups_kerning ) kerning->x = sfnt->get_gpos_kerning( ttface, left_glyph, right_glyph ); diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h index 3e1cf234fcf..943eaae3482 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h @@ -4,7 +4,7 @@ * * High-level TrueType driver interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h index 7ad937bd04d..631dbf5a80f 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h @@ -4,7 +4,7 @@ * * TrueType error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c index b656ccf04e3..e810ebfd550 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -660,7 +660,7 @@ } while ( subglyph->flags & MORE_COMPONENTS ); gloader->current.num_subglyphs = num_subglyphs; - FT_TRACE5(( " %d component%s\n", + FT_TRACE5(( " %u component%s\n", num_subglyphs, num_subglyphs > 1 ? "s" : "" )); @@ -674,7 +674,7 @@ for ( i = 0; i < num_subglyphs; i++ ) { if ( num_subglyphs > 1 ) - FT_TRACE7(( " subglyph %d:\n", i )); + FT_TRACE7(( " subglyph %u:\n", i )); FT_TRACE7(( " glyph index: %d\n", subglyph->index )); @@ -777,15 +777,11 @@ TT_Hint_Glyph( TT_Loader loader, FT_Bool is_composite ) { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - TT_Face face = loader->face; - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); -#endif - TT_GlyphZone zone = &loader->zone; #ifdef TT_USE_BYTECODE_INTERPRETER TT_ExecContext exec = loader->exec; + TT_Size size = loader->size; FT_Long n_ins = exec->glyphSize; #else FT_UNUSED( is_composite ); @@ -797,9 +793,6 @@ if ( n_ins > 0 ) FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); - /* Reset graphics state. */ - exec->GS = loader->size->GS; - /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ /* completely refer to the (already) hinted subglyphs. */ if ( is_composite ) @@ -811,8 +804,8 @@ } else { - exec->metrics.x_scale = loader->size->metrics->x_scale; - exec->metrics.y_scale = loader->size->metrics->y_scale; + exec->metrics.x_scale = size->metrics->x_scale; + exec->metrics.y_scale = size->metrics->y_scale; } #endif @@ -838,7 +831,7 @@ exec->is_composite = is_composite; exec->pts = *zone; - error = TT_Run_Context( exec ); + error = TT_Run_Context( exec, size ); if ( error && exec->pedantic_hinting ) return error; @@ -854,8 +847,7 @@ /* to change bearings or advance widths. */ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - exec->backward_compatibility ) + if ( exec->backward_compatibility ) return FT_Err_Ok; #endif @@ -1152,30 +1144,15 @@ x = FT_MulFix( x, x_scale ); y = FT_MulFix( y, y_scale ); - if ( subglyph->flags & ROUND_XY_TO_GRID ) + if ( subglyph->flags & ROUND_XY_TO_GRID && + IS_HINTED( loader->load_flags ) ) { - TT_Face face = loader->face; - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + if ( !loader->exec->backward_compatibility ) +#endif + x = FT_PIX_ROUND( x ); - - if ( IS_HINTED( loader->load_flags ) ) - { - /* - * We round the horizontal offset only if there is hinting along - * the x axis; this corresponds to integer advance width values. - * - * Theoretically, a glyph's bytecode can toggle ClearType's - * `backward compatibility' mode, which would allow modification - * of the advance width. In reality, however, applications - * neither allow nor expect modified advance widths if subpixel - * rendering is active. - * - */ - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 ) - x = FT_PIX_ROUND( x ); - - y = FT_PIX_ROUND( y ); - } + y = FT_PIX_ROUND( y ); } } } @@ -1204,8 +1181,6 @@ { FT_Error error; FT_Outline* outline = &loader->gloader->base.outline; - FT_Stream stream = loader->stream; - FT_UShort n_ins; FT_UInt i; @@ -1224,8 +1199,10 @@ #ifdef TT_USE_BYTECODE_INTERPRETER { - TT_ExecContext exec = loader->exec; + TT_ExecContext exec = loader->exec; FT_Memory memory = exec->memory; + FT_Stream stream = loader->stream; + FT_UShort n_ins; if ( exec->glyphSize ) @@ -1378,8 +1355,9 @@ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && loader->exec && - loader->exec->subpixel_hinting_lean && - loader->exec->grayscale_cleartype ) + loader->exec->mode != FT_RENDER_MODE_MONO && + loader->exec->mode != FT_RENDER_MODE_LCD && + loader->exec->mode != FT_RENDER_MODE_LCD_V ) { loader->pp3.x = loader->advance / 2; loader->pp4.x = loader->advance / 2; @@ -1444,13 +1422,13 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( recurse_count ) - FT_TRACE5(( " nesting level: %d\n", recurse_count )); + FT_TRACE5(( " nesting level: %u\n", recurse_count )); #endif /* some fonts have an incorrect value of `maxComponentDepth' */ if ( recurse_count > face->max_profile.maxComponentDepth ) { - FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n", + FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %u\n", recurse_count )); face->max_profile.maxComponentDepth = (FT_UShort)recurse_count; } @@ -1566,18 +1544,18 @@ if ( header_only ) goto Exit; +#ifdef FT_CONFIG_OPTION_INCREMENTAL + tt_get_metrics_incremental( loader, glyph_index ); +#endif + tt_loader_set_pp( loader ); + + /* shortcut for empty glyphs */ if ( loader->byte_len == 0 || loader->n_contours == 0 ) { -#ifdef FT_CONFIG_OPTION_INCREMENTAL - tt_get_metrics_incremental( loader, glyph_index ); -#endif - tt_loader_set_pp( loader ); - #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || - FT_IS_VARIATION( FT_FACE( face ) ) ) + if ( !IS_DEFAULT_INSTANCE( FT_FACE( face ) ) ) { /* a small outline structure with four elements for */ /* communication with `TT_Vary_Apply_Glyph_Deltas' */ @@ -1627,11 +1605,6 @@ goto Exit; } -#ifdef FT_CONFIG_OPTION_INCREMENTAL - tt_get_metrics_incremental( loader, glyph_index ); -#endif - tt_loader_set_pp( loader ); - /***********************************************************************/ /***********************************************************************/ @@ -1735,8 +1708,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || - FT_IS_VARIATION( FT_FACE( face ) ) ) + if ( !IS_DEFAULT_INSTANCE( FT_FACE( face ) ) ) { FT_UShort i, limit; FT_SubGlyph subglyph; @@ -1953,6 +1925,9 @@ #ifdef FT_CONFIG_OPTION_INCREMENTAL + /* restore the original stream */ + loader->stream = face->root.stream; + if ( glyph_data_loaded ) face->root.internal->incremental_interface->funcs->free_glyph_data( face->root.internal->incremental_interface->object, @@ -2112,7 +2087,6 @@ { TT_Face face = (TT_Face)glyph->face; SFNT_Service sfnt = (SFNT_Service)face->sfnt; - FT_Stream stream = face->root.stream; FT_Error error; TT_SBit_MetricsRec sbit_metrics; @@ -2121,14 +2095,11 @@ size->strike_index, glyph_index, (FT_UInt)load_flags, - stream, + face->root.stream, &glyph->bitmap, &sbit_metrics ); if ( !error ) { - glyph->outline.n_points = 0; - glyph->outline.n_contours = 0; - glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64; glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64; @@ -2153,6 +2124,50 @@ glyph->bitmap_top = sbit_metrics.horiBearingY; } } + /* a missing glyph in a bitmap-only font is assumed whitespace */ + /* that needs to be constructed using metrics data from `hmtx' */ + /* and, optionally, `vmtx' tables */ + else if ( FT_ERR_EQ( error, Missing_Bitmap ) && + !FT_IS_SCALABLE( glyph->face ) && + face->horz_metrics_size ) + { + FT_Fixed x_scale = size->root.metrics.x_scale; + FT_Fixed y_scale = size->root.metrics.y_scale; + + FT_Short left_bearing = 0; + FT_Short top_bearing = 0; + + FT_UShort advance_width = 0; + FT_UShort advance_height = 0; + + + TT_Get_HMetrics( face, glyph_index, + &left_bearing, + &advance_width ); + TT_Get_VMetrics( face, glyph_index, + 0, + &top_bearing, + &advance_height ); + + glyph->metrics.width = 0; + glyph->metrics.height = 0; + + glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale ); + glyph->metrics.horiBearingY = 0; + glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale ); + + glyph->metrics.vertBearingX = 0; + glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale ); + glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale ); + + glyph->format = FT_GLYPH_FORMAT_BITMAP; + glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO; + + glyph->bitmap_left = 0; + glyph->bitmap_top = 0; + + error = FT_Err_Ok; + } return error; } @@ -2168,15 +2183,6 @@ FT_Bool glyf_table_only ) { TT_Face face = (TT_Face)glyph->face; - FT_Stream stream = face->root.stream; - -#ifdef TT_USE_BYTECODE_INTERPRETER - FT_Error error; - FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face ); -#endif -#endif FT_ZERO( loader ); @@ -2186,122 +2192,78 @@ /* load execution context */ if ( IS_HINTED( load_flags ) && !glyf_table_only ) { + FT_Error error; TT_ExecContext exec; - FT_Bool grayscale = TRUE; + FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); + FT_Bool grayscale = FT_BOOL( mode != FT_RENDER_MODE_MONO ); + FT_Bool reexecute = FALSE; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - FT_Bool subpixel_hinting_lean; - FT_Bool grayscale_cleartype; + TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face ); #endif - FT_Bool reexecute = FALSE; - - if ( size->bytecode_ready < 0 || size->cvt_ready < 0 ) + if ( size->bytecode_ready > 0 ) + return size->bytecode_ready; + if ( size->bytecode_ready < 0 ) { - error = tt_size_ready_bytecode( size, pedantic ); + FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); + + + error = tt_size_init_bytecode( size, pedantic ); if ( error ) return error; } - else if ( size->bytecode_ready ) - return size->bytecode_ready; - else if ( size->cvt_ready ) - return size->cvt_ready; - /* query new execution context */ exec = size->context; - if ( !exec ) - return FT_THROW( Could_Not_Find_Context ); - - grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) { - subpixel_hinting_lean = - FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != - FT_RENDER_MODE_MONO ); - grayscale_cleartype = - FT_BOOL( subpixel_hinting_lean && - !( ( load_flags & - FT_LOAD_TARGET_LCD ) || - ( load_flags & - FT_LOAD_TARGET_LCD_V ) ) ); - exec->vertical_lcd_lean = - FT_BOOL( subpixel_hinting_lean && - ( load_flags & - FT_LOAD_TARGET_LCD_V ) ); - grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean ); - } - else - { - subpixel_hinting_lean = FALSE; - grayscale_cleartype = FALSE; - exec->vertical_lcd_lean = FALSE; + grayscale = FALSE; + + /* any mode change requires a re-execution of the CVT program */ + if ( mode != exec->mode ) + { + FT_TRACE4(( "tt_loader_init: render mode change," + " re-executing `prep' table\n" )); + + exec->mode = mode; + reexecute = TRUE; + } } #endif + /* a change from mono to grayscale rendering (and vice versa) */ + /* requires a re-execution of the CVT program */ + if ( grayscale != exec->grayscale ) + { + FT_TRACE4(( "tt_loader_init: grayscale hinting change," + " re-executing `prep' table\n" )); + + exec->grayscale = grayscale; + reexecute = TRUE; + } + + if ( size->cvt_ready > 0 ) + return size->cvt_ready; + if ( size->cvt_ready < 0 || reexecute ) + { + error = tt_size_run_prep( size ); + if ( error ) + return error; + } + error = TT_Load_Context( exec, face, size ); if ( error ) return error; - { -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) - { - /* a change from mono to subpixel rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( subpixel_hinting_lean != exec->subpixel_hinting_lean ) - { - FT_TRACE4(( "tt_loader_init: subpixel hinting change," - " re-executing `prep' table\n" )); - - exec->subpixel_hinting_lean = subpixel_hinting_lean; - reexecute = TRUE; - } - - /* a change from colored to grayscale subpixel rendering (and */ - /* vice versa) requires a re-execution of the CVT program */ - if ( grayscale_cleartype != exec->grayscale_cleartype ) - { - FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change," - " re-executing `prep' table\n" )); - - exec->grayscale_cleartype = grayscale_cleartype; - reexecute = TRUE; - } - } -#endif - - /* a change from mono to grayscale rendering (and vice versa) */ - /* requires a re-execution of the CVT program */ - if ( grayscale != exec->grayscale ) - { - FT_TRACE4(( "tt_loader_init: grayscale hinting change," - " re-executing `prep' table\n" )); - - exec->grayscale = grayscale; - reexecute = TRUE; - } - } - - if ( reexecute ) - { - error = tt_size_run_prep( size, pedantic ); - if ( error ) - return error; - error = TT_Load_Context( exec, face, size ); - if ( error ) - return error; - } - /* check whether the cvt program has disabled hinting */ - if ( exec->GS.instruct_control & 1 ) + if ( size->GS.instruct_control & 1 ) load_flags |= FT_LOAD_NO_HINTING; - /* load default graphics state -- if needed */ - if ( exec->GS.instruct_control & 2 ) - exec->GS = tt_default_graphics_state; + /* check whether GS modifications should be reverted */ + if ( size->GS.instruct_control & 2 ) + size->GS = tt_default_graphics_state; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* @@ -2318,28 +2280,25 @@ * */ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - subpixel_hinting_lean && + mode != FT_RENDER_MODE_MONO && !FT_IS_TRICKY( glyph->face ) ) - exec->backward_compatibility = !( exec->GS.instruct_control & 4 ); + exec->backward_compatibility = ( size->GS.instruct_control & 4 ) ^ 4; else - exec->backward_compatibility = FALSE; + exec->backward_compatibility = 0; #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ - exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); loader->exec = exec; - loader->instructions = exec->glyphIns; /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */ /* is set or backward compatibility mode of the v38 or v40 */ /* interpreters is active. See `ttinterp.h' for details on */ /* backward compatibility mode. */ - if ( IS_HINTED( loader->load_flags ) && - !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) && + if ( IS_HINTED( load_flags ) && + !( load_flags & FT_LOAD_COMPUTE_METRICS ) && #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && - exec->backward_compatibility ) && + !exec->backward_compatibility && #endif - !face->postscript.isFixedPitch ) + !face->postscript.isFixedPitch ) { loader->widthp = size->widthp; } @@ -2364,7 +2323,7 @@ loader->face = face; loader->size = size; loader->glyph = (FT_GlyphSlot)glyph; - loader->stream = stream; + loader->stream = face->root.stream; loader->composites.head = NULL; loader->composites.tail = NULL; @@ -2426,84 +2385,26 @@ TT_LoaderRec loader; - FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index )); + FT_TRACE1(( "TT_Load_Glyph: glyph index %u\n", glyph_index )); #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS /* try to load embedded bitmap (if any) */ - if ( size->strike_index != 0xFFFFFFFFUL && - ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && - IS_DEFAULT_INSTANCE( glyph->face ) ) + if ( size->strike_index != 0xFFFFFFFFUL && + !( load_flags & FT_LOAD_NO_BITMAP && + FT_IS_SCALABLE( glyph->face ) ) && + IS_DEFAULT_INSTANCE( glyph->face ) ) { - FT_Fixed x_scale = size->root.metrics.x_scale; - FT_Fixed y_scale = size->root.metrics.y_scale; - - error = load_sbit_image( size, glyph, glyph_index, load_flags ); - if ( FT_ERR_EQ( error, Missing_Bitmap ) ) - { - /* the bitmap strike is incomplete and misses the requested glyph; */ - /* if we have a bitmap-only font, return an empty glyph */ - if ( !FT_IS_SCALABLE( glyph->face ) ) - { - FT_Short left_bearing = 0; - FT_Short top_bearing = 0; - - FT_UShort advance_width = 0; - FT_UShort advance_height = 0; - - - /* to return an empty glyph, however, we need metrics data */ - /* from the `hmtx' (or `vmtx') table; the assumption is that */ - /* empty glyphs are missing intentionally, representing */ - /* whitespace - not having at least horizontal metrics is */ - /* thus considered an error */ - if ( !face->horz_metrics_size ) - return error; - - /* we now construct an empty bitmap glyph */ - TT_Get_HMetrics( face, glyph_index, - &left_bearing, - &advance_width ); - TT_Get_VMetrics( face, glyph_index, - 0, - &top_bearing, - &advance_height ); - - glyph->outline.n_points = 0; - glyph->outline.n_contours = 0; - - glyph->metrics.width = 0; - glyph->metrics.height = 0; - - glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale ); - glyph->metrics.horiBearingY = 0; - glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale ); - - glyph->metrics.vertBearingX = 0; - glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale ); - glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale ); - - glyph->format = FT_GLYPH_FORMAT_BITMAP; - glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO; - - glyph->bitmap_left = 0; - glyph->bitmap_top = 0; - - return FT_Err_Ok; - } - } - else if ( error ) - { - /* return error if font is not scalable */ - if ( !FT_IS_SCALABLE( glyph->face ) ) - return error; - } - else + if ( !error ) { if ( FT_IS_SCALABLE( glyph->face ) || FT_HAS_SBIX( glyph->face ) ) { + FT_Fixed x_scale = size->root.metrics.x_scale; + FT_Fixed y_scale = size->root.metrics.y_scale; + + /* for the bbox we need the header only */ (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); @@ -2550,8 +2451,10 @@ y_scale ); } - return FT_Err_Ok; + goto Exit; } + else if ( !FT_IS_SCALABLE( glyph->face ) ) + goto Exit; } if ( load_flags & FT_LOAD_SBITS_ONLY ) @@ -2563,7 +2466,7 @@ #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ - if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) + if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.ppem ) { error = FT_THROW( Invalid_Size_Handle ); goto Exit; @@ -2614,7 +2517,7 @@ glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale ); glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale ); - return error; + goto Exit; } FT_TRACE3(( "Failed to load SVG glyph\n" )); @@ -2642,10 +2545,6 @@ goto Done; } - glyph->format = FT_GLYPH_FORMAT_OUTLINE; - glyph->num_subglyphs = 0; - glyph->outline.flags = 0; - /* main loading loop */ error = load_truetype_glyph( &loader, glyph_index, 0, FALSE ); if ( !error ) @@ -2657,9 +2556,18 @@ } else { + glyph->format = FT_GLYPH_FORMAT_OUTLINE; + glyph->outline = loader.gloader->base.outline; glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; + /* Set the `high precision' bit flag. This is _critical_ to */ + /* get correct output for monochrome TrueType glyphs at all */ + /* sizes using the bytecode interpreter. */ + if ( !( load_flags & FT_LOAD_NO_SCALE ) && + size->metrics->y_ppem < 24 ) + glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; + /* Translate array so that (0,0) is the glyph's origin. Note */ /* that this behaviour is independent on the value of bit 1 of */ /* the `flags' field in the `head' table -- at least major */ @@ -2708,14 +2616,6 @@ error = compute_glyph_metrics( &loader, glyph_index ); } - /* Set the `high precision' bit flag. */ - /* This is _critical_ to get correct output for monochrome */ - /* TrueType glyphs at all sizes using the bytecode interpreter. */ - /* */ - if ( !( load_flags & FT_LOAD_NO_SCALE ) && - size->metrics->y_ppem < 24 ) - glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - FT_TRACE1(( " subglyphs = %u, contours = %hu, points = %hu," " flags = 0x%.3x\n", loader.gloader->base.num_subglyphs, @@ -2727,11 +2627,8 @@ tt_loader_done( &loader ); Exit: -#ifdef FT_DEBUG_LEVEL_TRACE - if ( error ) - FT_TRACE1(( " failed (error code 0x%x)\n", - error )); -#endif + FT_TRACE1(( error ? " failed (error code 0x%x)\n" : "", + error )); return error; } diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h index 22ea967f301..39d6ae3664c 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h @@ -4,7 +4,7 @@ * * TrueType Glyph Loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c index 4f0083c96b7..0732fcbae36 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. * * This file is part of the FreeType project, and may only be used, @@ -489,8 +489,9 @@ FT_UShort axis_count; FT_UInt region_count; - FT_UInt i, j; - FT_Bool long_words; + FT_UInt i, j; + FT_Byte* bytes; + FT_Bool long_words; GX_Blend blend = ttface->blend; FT_ULong* dataOffsetArray = NULL; @@ -526,11 +527,15 @@ if ( FT_QNEW_ARRAY( dataOffsetArray, data_count ) ) goto Exit; + if ( FT_FRAME_ENTER( data_count * 4 ) ) + goto Exit; + + bytes = stream->cursor; + for ( i = 0; i < data_count; i++ ) - { - if ( FT_READ_ULONG( dataOffsetArray[i] ) ) - goto Exit; - } + dataOffsetArray[i] = FT_NEXT_ULONG( bytes ); + + FT_FRAME_EXIT(); /* parse array of region records (region list) */ if ( FT_STREAM_SEEK( offset + region_offset ) ) @@ -564,13 +569,26 @@ goto Exit; itemStore->regionCount = region_count; - for ( i = 0; i < itemStore->regionCount; i++ ) + if ( FT_FRAME_ENTER( (FT_Long)region_count * axis_count * 6 ) ) + { + FT_TRACE2(( "tt_var_load_item_variation_store:" + " not enough data for variation regions\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + bytes = stream->cursor; + + for ( i = 0; i < region_count; i++ ) { GX_AxisCoords axisCoords; if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, axis_count ) ) + { + FT_FRAME_EXIT(); goto Exit; + } axisCoords = itemStore->varRegionList[i].axisList; @@ -579,10 +597,9 @@ FT_Int start, peak, end; - if ( FT_READ_SHORT( start ) || - FT_READ_SHORT( peak ) || - FT_READ_SHORT( end ) ) - goto Exit; + start = FT_NEXT_SHORT( bytes ); + peak = FT_NEXT_SHORT( bytes ); + end = FT_NEXT_SHORT( bytes ); /* immediately tag invalid ranges with special peak = 0 */ if ( ( start < 0 && end > 0 ) || start > peak || peak > end ) @@ -594,6 +611,8 @@ } } + FT_FRAME_EXIT(); + /* end of region list parse */ /* use dataOffsetArray now to parse varData items */ @@ -625,7 +644,7 @@ /* check some data consistency */ if ( word_delta_count > region_idx_count ) { - FT_TRACE2(( "bad short count %d or region count %d\n", + FT_TRACE2(( "bad short count %d or region count %u\n", word_delta_count, region_idx_count )); error = FT_THROW( Invalid_Table ); @@ -634,7 +653,7 @@ if ( region_idx_count > itemStore->regionCount ) { - FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n", + FT_TRACE2(( "inconsistent regionCount %u in varData[%u]\n", region_idx_count, i )); error = FT_THROW( Invalid_Table ); @@ -648,20 +667,32 @@ varData->wordDeltaCount = word_delta_count; varData->longWords = long_words; + if ( FT_FRAME_ENTER( region_idx_count * 2 ) ) + { + FT_TRACE2(( "tt_var_load_item_variation_store:" + " not enough data for region indices\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + bytes = stream->cursor; + for ( j = 0; j < varData->regionIdxCount; j++ ) { - if ( FT_READ_USHORT( varData->regionIndices[j] ) ) - goto Exit; + varData->regionIndices[j] = FT_NEXT_USHORT( bytes ); if ( varData->regionIndices[j] >= itemStore->regionCount ) { - FT_TRACE2(( "bad region index %d\n", + FT_TRACE2(( "bad region index %u\n", varData->regionIndices[j] )); + FT_FRAME_EXIT(); error = FT_THROW( Invalid_Table ); goto Exit; } } + FT_FRAME_EXIT(); + per_region_size = word_delta_count + region_idx_count; if ( long_words ) per_region_size *= 2; @@ -706,6 +737,7 @@ FT_UInt innerIndexMask; FT_ULong i; FT_UInt j; + FT_Byte* bytes; if ( FT_STREAM_SEEK( offset ) || @@ -757,6 +789,16 @@ if ( FT_NEW_ARRAY( map->outerIndex, map->mapCount ) ) goto Exit; + if ( FT_FRAME_ENTER( map->mapCount * entrySize ) ) + { + FT_TRACE2(( "tt_var_load_delta_set_index_mapping:" + " invalid number of delta-set index mappings\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + bytes = stream->cursor; + for ( i = 0; i < map->mapCount; i++ ) { FT_UInt mapData = 0; @@ -769,9 +811,7 @@ FT_Byte data; - if ( FT_READ_BYTE( data ) ) - goto Exit; - + data = FT_NEXT_BYTE( bytes ); mapData = ( mapData << 8 ) | data; } @@ -789,7 +829,7 @@ if ( outerIndex >= itemStore->dataCount ) { - FT_TRACE2(( "outerIndex[%ld] == %d out of range\n", + FT_TRACE2(( "outerIndex[%lu] == %u out of range\n", i, outerIndex )); error = FT_THROW( Invalid_Table ); @@ -802,7 +842,7 @@ if ( innerIndex >= itemStore->varData[outerIndex].itemCount ) { - FT_TRACE2(( "innerIndex[%ld] == %d out of range\n", + FT_TRACE2(( "innerIndex[%lu] == %u out of range\n", i, innerIndex )); error = FT_THROW( Invalid_Table ); @@ -812,6 +852,8 @@ map->innerIndex[i] = innerIndex; } + FT_FRAME_EXIT(); + Exit: return error; } @@ -965,28 +1007,181 @@ } + static FT_Fixed + tt_calculate_scalar( GX_AxisCoords axis, + FT_UInt axisCount, + FT_Fixed* normalizedcoords ) + { + FT_Fixed scalar = 0x10000L; + FT_UInt j; + + + /* Inner loop steps through axes in this region. */ + for ( j = 0; j < axisCount; j++, axis++ ) + { + FT_Fixed ncv = normalizedcoords[j]; + + + /* Compute the scalar contribution of this axis, */ + /* with peak of 0 used for invalid axes. */ + if ( axis->peakCoord == ncv || + axis->peakCoord == 0 ) + continue; + + /* Ignore this region if coordinates are out of range. */ + else if ( ncv <= axis->startCoord || + ncv >= axis->endCoord ) + { + scalar = 0; + break; + } + + /* Cumulative product of all the axis scalars. */ + else if ( ncv < axis->peakCoord ) + scalar = FT_MulDiv( scalar, + ncv - axis->startCoord, + axis->peakCoord - axis->startCoord ); + else /* ncv > axis->peakCoord */ + scalar = FT_MulDiv( scalar, + axis->endCoord - ncv, + axis->endCoord - axis->peakCoord ); + + } /* per-axis loop */ + + return scalar; + } + + + static FT_Int64 + ft_mul_add_delta_scalar( FT_Int64 returnValue, + FT_Int32 delta, + FT_Int32 scalar ) + { + +#ifdef FT_INT64 + + return returnValue + (FT_Int64)delta * scalar; + +#else /* !FT_INT64 */ + + if ( (FT_UInt32)( delta + 0x8000 ) <= 0x20000 ) + { + /* Fast path: multiplication result fits into 32 bits. */ + + FT_Int32 lo = delta * scalar; + + + returnValue.lo += (FT_UInt32)lo; + + if ( returnValue.lo < (FT_UInt32)lo ) + returnValue.hi += ( lo < 0 ) ? 0 : 1; + + if ( lo < 0 ) + returnValue.hi -= 1; + + return returnValue; + } + else + { + /* Slow path: full 32x32 -> 64-bit signed multiplication. */ + + FT_Int64 product; + + /* Get absolute values. */ + FT_UInt32 a = ( delta < 0 ) ? -delta : delta; + FT_UInt32 b = ( scalar < 0 ) ? -scalar : scalar; + + /* Prepare unsigned multiplication. */ + FT_UInt32 a_lo = a & 0xFFFF; + FT_UInt32 a_hi = a >> 16; + + FT_UInt32 b_lo = b & 0xFFFF; + FT_UInt32 b_hi = b >> 16; + + /* Partial products. */ + FT_UInt32 p0 = a_lo * b_lo; + FT_UInt32 p1 = a_lo * b_hi; + FT_UInt32 p2 = a_hi * b_lo; + FT_UInt32 p3 = a_hi * b_hi; + + /* Combine: result = p3 << 32 + (p1 + p2) << 16 + p0 */ + FT_UInt32 mid = p1 + p2; + FT_UInt32 mid_carry = ( mid < p1 ); + + FT_UInt32 carry; + + + product.lo = ( mid << 16 ) + ( p0 & 0xFFFF ); + carry = ( product.lo < ( p0 & 0xFFFF ) ) ? 1 : 0; + product.hi = p3 + ( mid >> 16 ) + mid_carry + carry; + + /* If result should be negative, negate. */ + if ( ( delta < 0 ) ^ ( scalar < 0 ) ) + { + product.lo = ~product.lo + 1; + product.hi = ~product.hi + ( product.lo == 0 ? 1 : 0 ); + } + + /* Add to `returnValue`. */ + returnValue.lo += product.lo; + if ( returnValue.lo < product.lo ) + returnValue.hi++; + returnValue.hi += product.hi; + + return returnValue; + } + +#endif /* !FT_INT64 */ + + } + + + static FT_ItemVarDelta + ft_round_and_shift16( FT_Int64 returnValue ) + { + +#ifdef FT_INT64 + + return (FT_ItemVarDelta)( returnValue + 0x8000L ) >> 16; + +#else /* !FT_INT64 */ + + FT_UInt hi = returnValue.hi; + FT_UInt lo = returnValue.lo; + + FT_UInt delta; + + + /* Add 0x8000 to round. */ + lo += 0x8000; + if ( lo < 0x8000 ) /* overflow occurred */ + hi += 1; + + /* Shift right by 16 bits. */ + delta = ( hi << 16 ) | ( lo >> 16 ); + + return (FT_ItemVarDelta)delta; + +#endif /* !FT_INT64 */ + + } + + FT_LOCAL_DEF( FT_ItemVarDelta ) tt_var_get_item_delta( FT_Face face, /* TT_Face */ GX_ItemVarStore itemStore, FT_UInt outerIndex, FT_UInt innerIndex ) { - TT_Face ttface = (TT_Face)face; - FT_Stream stream = FT_FACE_STREAM( face ); - FT_Memory memory = stream->memory; - FT_Error error = FT_Err_Ok; + TT_Face ttface = (TT_Face)face; - GX_ItemVarData varData; - FT_ItemVarDelta* deltaSet = NULL; - FT_ItemVarDelta deltaSetStack[16]; + GX_ItemVarData varData; - FT_Fixed* scalars = NULL; - FT_Fixed scalarsStack[16]; - - FT_UInt master, j; - FT_ItemVarDelta returnValue = 0; - FT_UInt per_region_size; - FT_Byte* bytes; + FT_UInt master; + FT_Int64 returnValue = FT_INT64_ZERO; + FT_UInt shift_base = 1; + FT_UInt per_region_size; + FT_Byte* bytes; if ( !ttface->blend || !ttface->blend->normalizedcoords ) @@ -1011,113 +1206,63 @@ if ( varData->regionIdxCount == 0 ) return 0; /* Avoid "applying zero offset to null pointer". */ - if ( varData->regionIdxCount < 16 ) - { - deltaSet = deltaSetStack; - scalars = scalarsStack; - } - else - { - if ( FT_QNEW_ARRAY( deltaSet, varData->regionIdxCount ) ) - goto Exit; - if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) ) - goto Exit; - } - /* Parse delta set. */ /* */ /* Deltas are (word_delta_count + region_idx_count) bytes each */ /* if `longWords` isn't set, and twice as much otherwise. */ per_region_size = varData->wordDeltaCount + varData->regionIdxCount; if ( varData->longWords ) + { + shift_base = 2; per_region_size *= 2; + } bytes = varData->deltaSet + per_region_size * innerIndex; - if ( varData->longWords ) - { - for ( master = 0; master < varData->wordDeltaCount; master++ ) - deltaSet[master] = FT_NEXT_LONG( bytes ); - for ( ; master < varData->regionIdxCount; master++ ) - deltaSet[master] = FT_NEXT_SHORT( bytes ); - } - else - { - for ( master = 0; master < varData->wordDeltaCount; master++ ) - deltaSet[master] = FT_NEXT_SHORT( bytes ); - for ( ; master < varData->regionIdxCount; master++ ) - deltaSet[master] = FT_NEXT_CHAR( bytes ); - } - /* outer loop steps through master designs to be blended */ for ( master = 0; master < varData->regionIdxCount; master++ ) { - FT_Fixed scalar = 0x10000L; - FT_UInt regionIndex = varData->regionIndices[master]; + FT_UInt regionIndex = varData->regionIndices[master]; GX_AxisCoords axis = itemStore->varRegionList[regionIndex].axisList; + FT_Fixed scalar = tt_calculate_scalar( + axis, + itemStore->axisCount, + ttface->blend->normalizedcoords ); - /* inner loop steps through axes in this region */ - for ( j = 0; j < itemStore->axisCount; j++, axis++ ) + + if ( scalar ) { - FT_Fixed ncv = ttface->blend->normalizedcoords[j]; + FT_Int delta; - /* compute the scalar contribution of this axis */ - /* with peak of 0 used for invalid axes */ - if ( axis->peakCoord == ncv || - axis->peakCoord == 0 ) - continue; - - /* ignore this region if coords are out of range */ - else if ( ncv <= axis->startCoord || - ncv >= axis->endCoord ) + if ( varData->longWords ) { - scalar = 0; - break; + if ( master < varData->wordDeltaCount ) + delta = FT_NEXT_LONG( bytes ); + else + delta = FT_NEXT_SHORT( bytes ); + } + else + { + if ( master < varData->wordDeltaCount ) + delta = FT_NEXT_SHORT( bytes ); + else + delta = FT_NEXT_CHAR( bytes ); } - /* cumulative product of all the axis scalars */ - else if ( ncv < axis->peakCoord ) - scalar = FT_MulDiv( scalar, - ncv - axis->startCoord, - axis->peakCoord - axis->startCoord ); - else /* ncv > axis->peakCoord */ - scalar = FT_MulDiv( scalar, - axis->endCoord - ncv, - axis->endCoord - axis->peakCoord ); - - } /* per-axis loop */ - - scalars[master] = scalar; + returnValue = ft_mul_add_delta_scalar( returnValue, delta, scalar ); + } + else + { + /* Branch-free, yay. */ + bytes += shift_base << ( master < varData->wordDeltaCount ); + } } /* per-region loop */ - - /* Compute the scaled delta for this region. - * - * From: https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables: - * - * `Fixed` is a 32-bit (16.16) type and, in the general case, requires - * 32-bit deltas. As described above, the `DeltaSet` record can - * accommodate deltas that are, logically, either 16-bit or 32-bit. - * When scaled deltas are applied to `Fixed` values, the `Fixed` value - * is treated like a 32-bit integer. - * - * `FT_MulAddFix` internally uses 64-bit precision; it thus can handle - * deltas ranging from small 8-bit to large 32-bit values that are - * applied to 16.16 `FT_Fixed` / OpenType `Fixed` values. - */ - returnValue = FT_MulAddFix( scalars, deltaSet, varData->regionIdxCount ); - - Exit: - if ( scalars != scalarsStack ) - FT_FREE( scalars ); - if ( deltaSet != deltaSetStack ) - FT_FREE( deltaSet ); - - return returnValue; + return ft_round_and_shift16( returnValue ); } @@ -1643,6 +1788,7 @@ GX_Blend blend = face->blend; FT_Error error; FT_UInt i, j; + FT_Byte* bytes; FT_ULong table_len; FT_ULong gvar_start; FT_ULong offsetToData; @@ -1734,6 +1880,8 @@ if ( FT_FRAME_ENTER( offsets_len ) ) goto Exit; + bytes = stream->cursor; + /* offsets (one more offset than glyphs, to mark size of last) */ if ( FT_QNEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) ) goto Fail2; @@ -1744,16 +1892,24 @@ FT_ULong max_offset = 0; + if ( stream->limit - stream->cursor < gvar_head.glyphCount * 4 ) + { + FT_TRACE2(( "ft_var_load_gvar:" + " glyph variation data offset not enough\n" )); + error = FT_THROW( Invalid_Table ); + goto Fail; + } + for ( i = 0; i <= gvar_head.glyphCount; i++ ) { - blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG(); + blend->glyphoffsets[i] = offsetToData + FT_NEXT_ULONG( bytes ); if ( max_offset <= blend->glyphoffsets[i] ) max_offset = blend->glyphoffsets[i]; else { FT_TRACE2(( "ft_var_load_gvar:" - " glyph variation data offset %d not monotonic\n", + " glyph variation data offset %u not monotonic\n", i )); blend->glyphoffsets[i] = max_offset; } @@ -1762,7 +1918,7 @@ if ( limit < blend->glyphoffsets[i] ) { FT_TRACE2(( "ft_var_load_gvar:" - " glyph variation data offset %d out of range\n", + " glyph variation data offset %u out of range\n", i )); blend->glyphoffsets[i] = limit; } @@ -1774,16 +1930,24 @@ FT_ULong max_offset = 0; + if ( stream->limit - stream->cursor < gvar_head.glyphCount * 2 ) + { + FT_TRACE2(( "ft_var_load_gvar:" + " glyph variation data offset not enough\n" )); + error = FT_THROW( Invalid_Table ); + goto Fail; + } + for ( i = 0; i <= gvar_head.glyphCount; i++ ) { - blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2; + blend->glyphoffsets[i] = offsetToData + FT_NEXT_USHORT( bytes ) * 2; if ( max_offset <= blend->glyphoffsets[i] ) max_offset = blend->glyphoffsets[i]; else { FT_TRACE2(( "ft_var_load_gvar:" - " glyph variation data offset %d not monotonic\n", + " glyph variation data offset %u not monotonic\n", i )); blend->glyphoffsets[i] = max_offset; } @@ -1792,7 +1956,7 @@ if ( limit < blend->glyphoffsets[i] ) { FT_TRACE2(( "ft_var_load_gvar:" - " glyph variation data offset %d out of range\n", + " glyph variation data offset %u out of range\n", i )); blend->glyphoffsets[i] = limit; } @@ -1814,6 +1978,8 @@ goto Fail; } + bytes = stream->cursor; + if ( FT_QNEW_ARRAY( blend->tuplecoords, gvar_head.axisCount * gvar_head.globalCoordCount ) ) goto Fail2; @@ -1824,13 +1990,17 @@ for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ ) { blend->tuplecoords[i * gvar_head.axisCount + j] = - FT_fdot14ToFixed( FT_GET_SHORT() ); + FT_fdot14ToFixed( FT_NEXT_SHORT( bytes ) ); FT_TRACE5(( "%.5f ", (double)blend->tuplecoords[i * gvar_head.axisCount + j] / 65536 )); } FT_TRACE5(( "]\n" )); } + if ( FT_NEW_ARRAY( blend->tuplescalars, + gvar_head.globalCoordCount ) ) + goto Fail2; + blend->tuplecount = gvar_head.globalCoordCount; FT_TRACE5(( "\n" )); @@ -1896,15 +2066,25 @@ for ( i = 0; i < blend->num_axis; i++ ) { - FT_Fixed ncv = blend->normalizedcoords[i]; + FT_Fixed ncv; - FT_TRACE6(( " axis %d coordinate %.5f:\n", i, (double)ncv / 65536 )); + if ( tuple_coords[i] == 0 ) + { + FT_TRACE6(( " tuple coordinate is zero, ignore\n" )); + continue; + } - /* It's not clear why (for intermediate tuples) we don't need */ - /* to check against start/end -- the documentation says we don't. */ - /* Similarly, it's unclear why we don't need to scale along the */ - /* axis. */ + ncv = blend->normalizedcoords[i]; + + FT_TRACE6(( " axis %u coordinate %.5f:\n", i, (double)ncv / 65536 )); + + if ( ncv == 0 ) + { + FT_TRACE6(( " axis coordinate is zero, stop\n" )); + apply = 0; + break; + } if ( tuple_coords[i] == ncv ) { @@ -1914,12 +2094,6 @@ continue; } - if ( tuple_coords[i] == 0 ) - { - FT_TRACE6(( " tuple coordinate is zero, ignore\n" )); - continue; - } - if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) { /* not an intermediate tuple */ @@ -2001,7 +2175,7 @@ if ( num_coords > mmvar->num_axis ) { FT_TRACE2(( "ft_var_to_normalized:" - " only using first %d of %d coordinates\n", + " only using first %u of %u coordinates\n", mmvar->num_axis, num_coords )); num_coords = mmvar->num_axis; } @@ -2016,7 +2190,7 @@ FT_Fixed coord = coords[i]; - FT_TRACE5(( " %d: %.5f\n", i, (double)coord / 65536 )); + FT_TRACE5(( " %u: %.5f\n", i, (double)coord / 65536 )); if ( coord > a->maximum || coord < a->minimum ) { FT_TRACE1(( "ft_var_to_normalized: design coordinate %.5f\n", @@ -2156,7 +2330,7 @@ if ( num_coords > blend->num_axis ) { FT_TRACE2(( "ft_var_to_design:" - " only using first %d of %d coordinates\n", + " only using first %u of %u coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } @@ -2516,7 +2690,7 @@ " minimum default maximum flags\n" )); /* " XXXX.XXXXX XXXX.XXXXX XXXX.XXXXX 0xXXXX" */ - FT_TRACE5(( " %3d `%s'" + FT_TRACE5(( " %3u `%s'" " %10.5f %10.5f %10.5f 0x%04X%s\n", i, a->name, @@ -2608,7 +2782,7 @@ (void)FT_STREAM_SEEK( pos ); - FT_TRACE5(( " named instance %d (%s%s%s, %s%s%s)\n", + FT_TRACE5(( " named instance %u (%s%s%s, %s%s%s)\n", i, strname ? "name: `" : "", strname ? strname : "unnamed", @@ -2636,7 +2810,7 @@ FT_UInt strid = ~0U; - /* The default instance is missing in array the */ + /* The default instance is missing in the array */ /* of named instances; try to synthesize an entry. */ /* If this fails, `default_named_instance` remains */ /* at value zero, which doesn't do any harm. */ @@ -2766,10 +2940,18 @@ } manageCvt; - face->doblend = FALSE; - if ( !face->blend ) { + face->doblend = FALSE; + for ( i = 0; i < num_coords; i++ ) + if ( coords[i] ) + { + face->doblend = TRUE; + break; + } + if ( !face->doblend ) + goto Exit; + if ( FT_SET_ERROR( TT_Get_MM_Var( FT_FACE( face ), NULL ) ) ) goto Exit; } @@ -2780,7 +2962,7 @@ if ( num_coords > mmvar->num_axis ) { FT_TRACE2(( "TT_Set_MM_Blend:" - " only using first %d of %d coordinates\n", + " only using first %u of %u coordinates\n", mmvar->num_axis, num_coords )); num_coords = mmvar->num_axis; } @@ -2882,11 +3064,7 @@ /* return value -1 indicates `no change' */ if ( !have_diff ) - { - face->doblend = TRUE; - return -1; - } for ( ; i < mmvar->num_axis; i++ ) { @@ -2915,7 +3093,15 @@ blend->normalizedcoords, blend->coords ); - face->doblend = TRUE; + face->doblend = FALSE; + for ( i = 0; i < blend->num_axis; i++ ) + { + if ( blend->normalizedcoords[i] ) + { + face->doblend = TRUE; + break; + } + } if ( face->cvt ) { @@ -2941,6 +3127,9 @@ } } + for ( i = 0 ; i < blend->tuplecount ; i++ ) + blend->tuplescalars[i] = (FT_Fixed)-0x20000L; + Exit: return error; } @@ -2980,7 +3169,24 @@ FT_UInt num_coords, FT_Fixed* coords ) { - return tt_set_mm_blend( (TT_Face)face, num_coords, coords, 1 ); + FT_Error error; + + + error = tt_set_mm_blend( (TT_Face)face, num_coords, coords, 1 ); + if ( error == FT_Err_Ok ) + { + FT_UInt i; + + + for ( i = 0; i < num_coords; i++ ) + if ( coords[i] ) + { + error = -2; /* -2 means is_variable. */ + break; + } + } + + return error; } @@ -3043,7 +3249,7 @@ if ( num_coords > blend->num_axis ) { FT_TRACE2(( "TT_Get_MM_Blend:" - " only using first %d of %d coordinates\n", + " only using first %u of %u coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } @@ -3125,7 +3331,7 @@ if ( num_coords > mmvar->num_axis ) { FT_TRACE2(( "TT_Set_Var_Design:" - " only using first %d of %d coordinates\n", + " only using first %u of %u coordinates\n", mmvar->num_axis, num_coords )); num_coords = mmvar->num_axis; } @@ -3201,6 +3407,15 @@ if ( error ) goto Exit; + for ( i = 0; i < num_coords; i++ ) + { + if ( normalized[i] ) + { + error = -2; /* -2 means is_variable. */ + break; + } + } + Exit: FT_FREE( normalized ); return error; @@ -3237,10 +3452,12 @@ FT_UInt num_coords, FT_Fixed* coords ) { - TT_Face ttface = (TT_Face)face; - FT_Error error = FT_Err_Ok; - GX_Blend blend; - FT_UInt i, nc; + TT_Face ttface = (TT_Face)face; + FT_Error error = FT_Err_Ok; + GX_Blend blend; + FT_MM_Var* mmvar; + FT_Var_Axis* a; + FT_UInt i, nc; if ( !ttface->blend ) @@ -3263,24 +3480,26 @@ if ( num_coords > blend->num_axis ) { FT_TRACE2(( "TT_Get_Var_Design:" - " only using first %d of %d coordinates\n", + " only using first %u of %u coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } + mmvar = blend->mmvar; + a = mmvar->axis; if ( ttface->doblend ) { - for ( i = 0; i < nc; i++ ) + for ( i = 0; i < nc; i++, a++ ) coords[i] = blend->coords[i]; } else { - for ( i = 0; i < nc; i++ ) - coords[i] = 0; + for ( i = 0; i < nc; i++, a++ ) + coords[i] = a->def; } - for ( ; i < num_coords; i++ ) - coords[i] = 0; + for ( ; i < num_coords; i++, a++ ) + coords[i] = a->def; return FT_Err_Ok; } @@ -3373,6 +3592,9 @@ error = TT_Set_Var_Design( face, 0, NULL ); } + if ( error == -1 || error == -2 ) + error = FT_Err_Ok; + Exit: return error; } @@ -3591,7 +3813,7 @@ FT_Stream_SeekSet( stream, here ); } - FT_TRACE5(( "cvar: there %s %d tuple%s:\n", + FT_TRACE5(( "cvar: there %s %u tuple%s:\n", ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "is" : "are", tupleCount & GX_TC_TUPLE_COUNT_MASK, ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" )); @@ -3610,7 +3832,7 @@ FT_Fixed apply; - FT_TRACE6(( " tuple %d:\n", i )); + FT_TRACE6(( " tuple %u:\n", i )); tupleDataSize = FT_GET_USHORT(); tupleIndex = FT_GET_USHORT(); @@ -3676,7 +3898,7 @@ if ( !points || !deltas ) ; /* failure, ignore it */ - else if ( localpoints == ALL_POINTS ) + else if ( points == ALL_POINTS ) { #ifdef FT_DEBUG_LEVEL_TRACE int count = 0; @@ -3697,7 +3919,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( old_cvt_delta != cvt_deltas[j] ) { - FT_TRACE7(( " %d: %f -> %f\n", + FT_TRACE7(( " %u: %f -> %f\n", j, (double)( FT_fdot6ToFixed( face->cvt[j] ) + old_cvt_delta ) / 65536, @@ -4027,7 +4249,7 @@ FT_Outline* outline, FT_Vector* unrounded ) { - FT_Error error; + FT_Error error = FT_Err_Ok; TT_Face face = loader->face; FT_Stream stream = face->root.stream; FT_Memory memory = stream->memory; @@ -4047,6 +4269,15 @@ FT_ULong here; FT_UInt i, j; + FT_UInt peak_coords_size; + FT_UInt point_deltas_x_size; + FT_UInt points_org_size; + FT_UInt points_out_size; + FT_UInt has_delta_size; + FT_UInt pool_size; + FT_Byte* pool = NULL; + FT_Byte* p; + FT_Fixed* peak_coords = NULL; FT_Fixed* tuple_coords; FT_Fixed* im_start_coords; @@ -4067,21 +4298,24 @@ FT_Fixed* point_deltas_y = NULL; - if ( !face->doblend || !blend ) - return FT_THROW( Invalid_Argument ); - for ( i = 0; i < n_points; i++ ) { unrounded[i].x = INT_TO_F26DOT6( outline->points[i].x ); unrounded[i].y = INT_TO_F26DOT6( outline->points[i].y ); } + if ( !face->doblend ) + goto Exit; + + if ( !blend ) + return FT_THROW( Invalid_Argument ); + if ( glyph_index >= blend->gv_glyphcnt || blend->glyphoffsets[glyph_index] == blend->glyphoffsets[glyph_index + 1] ) { FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" - " no variation data for glyph %d\n", glyph_index )); + " no variation data for glyph %u\n", glyph_index )); return FT_Err_Ok; } @@ -4125,18 +4359,41 @@ FT_Stream_SeekSet( stream, here ); } - FT_TRACE5(( "gvar: there %s %d tuple%s:\n", + FT_TRACE5(( "gvar: there %s %u tuple%s:\n", ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "is" : "are", tupleCount & GX_TC_TUPLE_COUNT_MASK, ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" )); - if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) || - FT_NEW_ARRAY( point_deltas_x, 2 * n_points ) || - FT_QNEW_ARRAY( points_org, n_points ) || - FT_QNEW_ARRAY( points_out, n_points ) || - FT_QNEW_ARRAY( has_delta, n_points ) ) + peak_coords_size = ALIGN_SIZE( 3 * blend->num_axis * + sizeof ( *peak_coords ) ); + point_deltas_x_size = ALIGN_SIZE( 2 * n_points * + sizeof ( *point_deltas_x ) ); + points_org_size = ALIGN_SIZE( n_points * sizeof ( *points_org ) ); + points_out_size = ALIGN_SIZE( n_points * sizeof ( *points_out ) ); + has_delta_size = ALIGN_SIZE( n_points * sizeof ( *has_delta ) ); + + pool_size = peak_coords_size + + point_deltas_x_size + + points_org_size + + points_out_size + + has_delta_size; + + if ( FT_ALLOC( pool, pool_size ) ) goto Exit; + p = pool; + peak_coords = (FT_Fixed*)p; + p += peak_coords_size; + point_deltas_x = (FT_Fixed*)p; + p += point_deltas_x_size; + points_org = (FT_Vector*)p; + p += points_org_size; + points_out = (FT_Vector*)p; + p += points_out_size; + has_delta = (FT_Bool*)p; + + FT_ARRAY_ZERO( point_deltas_x, 2 * n_points ); + im_start_coords = peak_coords + blend->num_axis; im_end_coords = im_start_coords + blend->num_axis; point_deltas_y = point_deltas_x + n_points; @@ -4147,27 +4404,70 @@ points_org[j].y = FT_intToFixed( outline->points[j].y ); } - for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ ) + p = stream->cursor; + + tupleCount &= GX_TC_TUPLE_COUNT_MASK; + for ( i = 0; i < tupleCount; i++ ) { - FT_UInt tupleDataSize; - FT_UInt tupleIndex; - FT_Fixed apply; + FT_UInt tupleDataSize; + FT_UInt tupleIndex; + FT_Fixed apply; + FT_Fixed* tupleScalars; - FT_TRACE6(( " tuple %d:\n", i )); + FT_TRACE6(( " tuple %u:\n", i )); - tupleDataSize = FT_GET_USHORT(); - tupleIndex = FT_GET_USHORT(); + tupleScalars = blend->tuplescalars; + + /* Enter frame for four bytes. */ + if ( 4 > stream->limit - p ) + { + FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" + " invalid glyph variation array header\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + + tupleDataSize = FT_NEXT_USHORT( p ); + tupleIndex = FT_NEXT_USHORT( p ); + + if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) + tupleScalars = NULL; if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) { + if ( 2 * blend->num_axis > (FT_UInt)( stream->limit - p ) ) + { + FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" + " invalid glyph variation array header\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + for ( j = 0; j < blend->num_axis; j++ ) - peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + peak_coords[j] = FT_fdot14ToFixed( FT_NEXT_SHORT( p ) ); + tuple_coords = peak_coords; + tupleScalars = NULL; } else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount ) + { + FT_Fixed scalar = + tupleScalars + ? tupleScalars[tupleIndex & GX_TI_TUPLE_INDEX_MASK] + : (FT_Fixed)-0x20000; + + + if ( scalar != (FT_Fixed)-0x20000 ) + { + apply = scalar; + goto apply_found; + } + tuple_coords = blend->tuplecoords + - ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis; + ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * + blend->num_axis; + } else { FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" @@ -4179,10 +4479,18 @@ if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) { + if ( 4 * blend->num_axis > (FT_UInt)( stream->limit - p ) ) + { + FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" + " invalid glyph variation array header\n" )); + error = FT_THROW( Invalid_Table ); + goto Exit; + } + for ( j = 0; j < blend->num_axis; j++ ) - im_start_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + im_start_coords[j] = FT_fdot14ToFixed( FT_NEXT_SHORT( p ) ); for ( j = 0; j < blend->num_axis; j++ ) - im_end_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + im_end_coords[j] = FT_fdot14ToFixed( FT_NEXT_SHORT( p ) ); } apply = ft_var_apply_tuple( blend, @@ -4191,6 +4499,11 @@ im_start_coords, im_end_coords ); + if ( tupleScalars ) + tupleScalars[tupleIndex & GX_TI_TUPLE_INDEX_MASK] = apply; + + apply_found: + if ( apply == 0 ) /* tuple isn't active for our blend */ { offsetToData += tupleDataSize; @@ -4247,7 +4560,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( point_delta_x || point_delta_y ) { - FT_TRACE7(( " %d: (%f, %f) -> (%f, %f)\n", + FT_TRACE7(( " %u: (%f, %f) -> (%f, %f)\n", j, (double)( FT_intToFixed( outline->points[j].x ) + old_point_delta_x ) / 65536, @@ -4321,7 +4634,7 @@ #ifdef FT_DEBUG_LEVEL_TRACE if ( point_delta_x || point_delta_y ) { - FT_TRACE7(( " %d: (%f, %f) -> (%f, %f)\n", + FT_TRACE7(( " %u: (%f, %f) -> (%f, %f)\n", j, (double)( FT_intToFixed( outline->points[j].x ) + old_point_delta_x ) / 65536, @@ -4402,11 +4715,7 @@ Exit: if ( sharedpoints != ALL_POINTS ) FT_FREE( sharedpoints ); - FT_FREE( points_org ); - FT_FREE( points_out ); - FT_FREE( has_delta ); - FT_FREE( peak_coords ); - FT_FREE( point_deltas_x ); + FT_FREE( pool ); FExit: FT_FRAME_EXIT(); @@ -4577,6 +4886,7 @@ FT_FREE( blend->mvar_table ); } + FT_FREE( blend->tuplescalars ); FT_FREE( blend->tuplecoords ); FT_FREE( blend->glyphoffsets ); FT_FREE( blend ); diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h index 9326011e3a2..568c8027bbf 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h @@ -4,7 +4,7 @@ * * TrueType GX Font Variation loader (specification) * - * Copyright (C) 2004-2024 by + * Copyright (C) 2004-2025 by * David Turner, Robert Wilhelm, Werner Lemberg and George Williams. * * This file is part of the FreeType project, and may only be used, @@ -255,6 +255,10 @@ FT_BEGIN_HEADER * A two-dimensional array that holds the shared tuple coordinates * in the `gvar' table. * + * tuplescalars :: + * A one-dimensional array that holds the shared tuple + * scalars in the `gvar' table for current face coordinates. + * * gv_glyphcnt :: * The number of glyphs handled in the `gvar' table. * @@ -293,6 +297,7 @@ FT_BEGIN_HEADER FT_UInt tuplecount; FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ + FT_Fixed* tuplescalars; /* tuplescalars[tuplecount] */ FT_UInt gv_glyphcnt; FT_ULong* glyphoffsets; /* glyphoffsets[gv_glyphcnt + 1] */ diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c index 951891dbf51..7b26c9a9df2 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -27,6 +27,8 @@ #include #include +#ifdef TT_USE_BYTECODE_INTERPRETER + #include "ttinterp.h" #include "tterrors.h" #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT @@ -34,9 +36,6 @@ #endif -#ifdef TT_USE_BYTECODE_INTERPRETER - - /************************************************************************** * * The macro FT_COMPONENT is used in trace mode. It is an implicit @@ -89,6 +88,32 @@ #define FAILURE 1 + /* The default value for `scan_control' is documented as FALSE in the */ + /* TrueType specification. This is confusing since it implies a */ + /* Boolean value. However, this is not the case, thus both the */ + /* default values of our `scan_type' and `scan_control' fields (which */ + /* the documentation's `scan_control' variable is split into) are */ + /* zero. */ + /* */ + /* The rounding compensation should logically belong here but poorly */ + /* described in the OpenType specs. It was probably important in the */ + /* days of dot matrix printers. The values are referenced by color */ + /* as Gray, Black, and White in order. The Apple specification says */ + /* that the Gray compensation is always zero. The fourth value is */ + /* not described at all, but Greg says that it is the same as Gray. */ + /* FreeType sets all compensation values to zero. */ + + const TT_GraphicsState tt_default_graphics_state = + { + 0, 0, 0, 1, 1, 1, + { 0x4000, 0 }, { 0x4000, 0 }, { 0x4000, 0 }, + 1, 1, { 0, 0, 0, 0 }, + + 64, 68, 0, 0, 9, 3, + TRUE, 0, FALSE, 0 + }; + + /************************************************************************** * * CODERANGE FUNCTIONS @@ -96,53 +121,6 @@ */ - /************************************************************************** - * - * @Function: - * TT_Goto_CodeRange - * - * @Description: - * Switches to a new code range (updates the code related elements in - * `exec', and `IP'). - * - * @Input: - * range :: - * The new execution code range. - * - * IP :: - * The new IP in the new code range. - * - * @InOut: - * exec :: - * The target execution context. - */ - FT_LOCAL_DEF( void ) - TT_Goto_CodeRange( TT_ExecContext exec, - FT_Int range, - FT_Long IP ) - { - TT_CodeRange* coderange; - - - FT_ASSERT( range >= 1 && range <= 3 ); - - coderange = &exec->codeRangeTable[range - 1]; - - FT_ASSERT( coderange->base ); - - /* NOTE: Because the last instruction of a program may be a CALL */ - /* which will return to the first byte *after* the code */ - /* range, we test for IP <= Size instead of IP < Size. */ - /* */ - FT_ASSERT( IP <= coderange->size ); - - exec->code = coderange->base; - exec->codeSize = coderange->size; - exec->IP = IP; - exec->curRange = range; - } - - /************************************************************************** * * @Function: @@ -168,13 +146,19 @@ FT_LOCAL_DEF( void ) TT_Set_CodeRange( TT_ExecContext exec, FT_Int range, - void* base, + FT_Byte* base, FT_Long length ) { FT_ASSERT( range >= 1 && range <= 3 ); - exec->codeRangeTable[range - 1].base = (FT_Byte*)base; + exec->codeRangeTable[range - 1].base = base; exec->codeRangeTable[range - 1].size = length; + + exec->code = base; + exec->codeSize = length; + exec->IP = 0; + exec->curRange = range; + exec->iniRange = range; } @@ -224,9 +208,6 @@ * exec :: * A handle to the target execution context. * - * memory :: - * A handle to the parent memory object. - * * @Note: * Only the glyph loader and debugger should call this function. */ @@ -240,10 +221,6 @@ exec->maxPoints = 0; exec->maxContours = 0; - /* free stack */ - FT_FREE( exec->stack ); - exec->stackSize = 0; - /* free glyf cvt working area */ FT_FREE( exec->glyfCvt ); exec->glyfCvtSize = 0; @@ -300,72 +277,26 @@ TT_Face face, TT_Size size ) { - FT_Int i; - TT_MaxProfile* maxp; - FT_Error error; - FT_Memory memory = exec->memory; + FT_Memory memory = exec->memory; exec->face = face; - maxp = &face->max_profile; exec->size = size; - if ( size ) - { - exec->numFDefs = size->num_function_defs; - exec->maxFDefs = size->max_function_defs; - exec->numIDefs = size->num_instruction_defs; - exec->maxIDefs = size->max_instruction_defs; - exec->FDefs = size->function_defs; - exec->IDefs = size->instruction_defs; - exec->pointSize = size->point_size; - exec->tt_metrics = size->ttmetrics; - exec->metrics = *size->metrics; - - exec->maxFunc = size->max_func; - exec->maxIns = size->max_ins; - - for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) - exec->codeRangeTable[i] = size->codeRangeTable[i]; - - /* set graphics state */ - exec->GS = size->GS; - - exec->cvtSize = size->cvt_size; - exec->cvt = size->cvt; - - exec->storeSize = size->storage_size; - exec->storage = size->storage; - - exec->twilight = size->twilight; - - /* In case of multi-threading it can happen that the old size object */ - /* no longer exists, thus we must clear all glyph zone references. */ - FT_ZERO( &exec->zp0 ); - exec->zp1 = exec->zp0; - exec->zp2 = exec->zp0; - } - - /* XXX: We reserve a little more elements on the stack to deal safely */ - /* with broken fonts like arialbs, courbs, timesbs, etc. */ - if ( FT_QRENEW_ARRAY( exec->stack, - exec->stackSize, - maxp->maxStackElements + 32 ) ) - return error; - exec->stackSize = maxp->maxStackElements + 32; + /* CVT and storage are not persistent in FreeType */ + /* reset them after they might have been modifief */ + exec->storage = exec->stack + exec->stackSize; + exec->cvt = exec->storage + exec->storeSize; /* free previous glyph code range */ FT_FREE( exec->glyphIns ); exec->glyphSize = 0; - exec->pts.n_points = 0; - exec->pts.n_contours = 0; + exec->pointSize = size->point_size; + exec->tt_metrics = size->ttmetrics; + exec->metrics = *size->metrics; - exec->zp1 = exec->pts; - exec->zp2 = exec->pts; - exec->zp0 = exec->pts; - - exec->instruction_trap = FALSE; + exec->twilight = size->twilight; return FT_Err_Ok; } @@ -394,89 +325,22 @@ TT_Save_Context( TT_ExecContext exec, TT_Size size ) { - FT_Int i; + /* UNDOCUMENTED! */ + /* Only these GS values can be modified by the CVT program. */ - - /* XXX: Will probably disappear soon with all the code range */ - /* management, which is now rather obsolete. */ - /* */ - size->num_function_defs = exec->numFDefs; - size->num_instruction_defs = exec->numIDefs; - - size->max_func = exec->maxFunc; - size->max_ins = exec->maxIns; - - for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) - size->codeRangeTable[i] = exec->codeRangeTable[i]; + size->GS.minimum_distance = exec->GS.minimum_distance; + size->GS.control_value_cutin = exec->GS.control_value_cutin; + size->GS.single_width_cutin = exec->GS.single_width_cutin; + size->GS.single_width_value = exec->GS.single_width_value; + size->GS.delta_base = exec->GS.delta_base; + size->GS.delta_shift = exec->GS.delta_shift; + size->GS.auto_flip = exec->GS.auto_flip; + size->GS.instruct_control = exec->GS.instruct_control; + size->GS.scan_control = exec->GS.scan_control; + size->GS.scan_type = exec->GS.scan_type; } - /************************************************************************** - * - * @Function: - * TT_Run_Context - * - * @Description: - * Executes one or more instructions in the execution context. - * - * @Input: - * exec :: - * A handle to the target execution context. - * - * @Return: - * TrueType error code. 0 means success. - */ - FT_LOCAL_DEF( FT_Error ) - TT_Run_Context( TT_ExecContext exec ) - { - TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ); - - exec->zp0 = exec->pts; - exec->zp1 = exec->pts; - exec->zp2 = exec->pts; - - exec->GS.gep0 = 1; - exec->GS.gep1 = 1; - exec->GS.gep2 = 1; - - exec->GS.projVector.x = 0x4000; - exec->GS.projVector.y = 0x0000; - - exec->GS.freeVector = exec->GS.projVector; - exec->GS.dualVector = exec->GS.projVector; - - exec->GS.round_state = 1; - exec->GS.loop = 1; - - /* some glyphs leave something on the stack. so we clean it */ - /* before a new execution. */ - exec->top = 0; - exec->callTop = 0; - - return exec->face->interpreter( exec ); - } - - - /* The default value for `scan_control' is documented as FALSE in the */ - /* TrueType specification. This is confusing since it implies a */ - /* Boolean value. However, this is not the case, thus both the */ - /* default values of our `scan_type' and `scan_control' fields (which */ - /* the documentation's `scan_control' variable is split into) are */ - /* zero. */ - - const TT_GraphicsState tt_default_graphics_state = - { - 0, 0, 0, - { 0x4000, 0 }, - { 0x4000, 0 }, - { 0x4000, 0 }, - - 1, 64, 1, - TRUE, 68, 0, 0, 9, 3, - 0, FALSE, 0, 1, 1, 1 - }; - - /* documentation is in ttinterp.h */ FT_EXPORT_DEF( TT_ExecContext ) @@ -485,7 +349,8 @@ FT_Memory memory; FT_Error error; - TT_ExecContext exec = NULL; + TT_ExecContext exec = NULL; + FT_DebugHook_Func interp; if ( !driver ) @@ -497,6 +362,15 @@ if ( FT_NEW( exec ) ) goto Fail; + /* set `exec->interpreter' according to the debug hook present, */ + /* which is used by 'ttdebug'. */ + interp = driver->root.root.library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; + + if ( interp ) + exec->interpreter = (TT_Interpreter)interp; + else + exec->interpreter = (TT_Interpreter)TT_RunIns; + /* create callStack here, other allocations delayed */ exec->memory = memory; exec->callSize = 32; @@ -1160,20 +1034,35 @@ #undef PACK -#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER +#ifdef FT_INT64 + +#define TT_MulFix14( a, b ) TT_MulFix14_64( a, b ) + + static inline FT_F26Dot6 + TT_MulFix14_64( FT_F26Dot6 a, + FT_F2Dot14 b ) + { + FT_Int64 ab = MUL_INT64( a, b ); + + + ab = ADD_INT64( ab, 0x2000 + ( ab >> 63 ) ); /* rounding phase */ + + return (FT_F26Dot6)( ab >> 14 ); + } + +#elif !defined( FT_CONFIG_OPTION_NO_ASSEMBLER ) #if defined( __arm__ ) && \ ( defined( __thumb2__ ) || !defined( __thumb__ ) ) #define TT_MulFix14 TT_MulFix14_arm - static FT_Int32 + static __inline FT_Int32 TT_MulFix14_arm( FT_Int32 a, - FT_Int b ) + FT_Int32 b ) { FT_Int32 t, t2; - #if defined( __CC_ARM ) || defined( __ARMCC__ ) __asm @@ -1199,8 +1088,8 @@ #endif "adds %1, %1, %0\n\t" /* %1 += %0 */ "adc %2, %2, #0\n\t" /* %2 += carry */ - "mov %0, %1, lsr #14\n\t" /* %0 = %1 >> 16 */ - "orr %0, %0, %2, lsl #18\n\t" /* %0 |= %2 << 16 */ + "mov %0, %1, lsr #14\n\t" /* %0 = %1 >> 14 */ + "orr %0, %0, %2, lsl #18\n\t" /* %0 |= %2 << 18 */ : "=r"(a), "=&r"(t2), "=&r"(t) : "r"(a), "r"(b) : "cc" ); @@ -1210,49 +1099,60 @@ return a; } -#endif /* __arm__ && ( __thumb2__ || !__thumb__ ) */ +#elif defined( __i386__ ) || defined( _M_IX86 ) -#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ +#define TT_MulFix14 TT_MulFix14_i386 + /* documentation is in freetype.h */ -#if defined( __GNUC__ ) && \ - ( defined( __i386__ ) || defined( __x86_64__ ) ) - -#define TT_MulFix14 TT_MulFix14_long_long - - /* Temporarily disable the warning that C90 doesn't support `long long'. */ -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wlong-long" - - /* This is declared `noinline' because inlining the function results */ - /* in slower code. The `pure' attribute indicates that the result */ - /* only depends on the parameters. */ - static __attribute__(( noinline )) - __attribute__(( pure )) FT_Int32 - TT_MulFix14_long_long( FT_Int32 a, - FT_Int b ) + static __inline FT_Int32 + TT_MulFixi14_i386( FT_Int32 a, + FT_Int32 b ) { + FT_Int32 result; - long long ret = (long long)a * b; +#if defined( __GNUC__ ) - /* The following line assumes that right shifting of signed values */ - /* will actually preserve the sign bit. The exact behaviour is */ - /* undefined, but this is true on x86 and x86_64. */ - long long tmp = ret >> 63; + __asm__ __volatile__ ( + "imul %%edx\n" + "movl %%edx, %%ecx\n" + "sarl $31, %%ecx\n" + "addl $0x2000, %%ecx\n" + "addl %%ecx, %%eax\n" + "adcl $0, %%edx\n" + "shrl $14, %%eax\n" + "shll $18, %%edx\n" + "addl %%edx, %%eax\n" + : "=a"(result), "=d"(b) + : "a"(a), "d"(b) + : "%ecx", "cc" ); +#elif defined( _MSC_VER) - ret += 0x2000 + tmp; + __asm + { + mov eax, a + mov edx, b + imul edx + mov ecx, edx + sar ecx, 31 + add ecx, 2000h + add eax, ecx + adc edx, 0 + shr eax, 14 + shl edx, 18 + add eax, edx + mov result, eax + } - return (FT_Int32)( ret >> 14 ); +#endif + + return result; } -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic pop -#endif +#endif /* __i386__ || _M_IX86 */ -#endif /* __GNUC__ && ( __i386__ || __x86_64__ ) */ +#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ #ifndef TT_MulFix14 @@ -1262,92 +1162,59 @@ /* for platforms where sizeof(int) == 2. */ static FT_Int32 TT_MulFix14( FT_Int32 a, - FT_Int b ) + FT_Int16 b ) { - FT_Int32 sign; - FT_UInt32 ah, al, mid, lo, hi; + FT_Int32 m, hi; + FT_UInt32 l, lo; - sign = a ^ b; + /* compute a*b as 64-bit (hi_lo) value */ + l = (FT_UInt32)( ( a & 0xFFFFU ) * b ); + m = ( a >> 16 ) * b; - if ( a < 0 ) - a = -a; - if ( b < 0 ) - b = -b; + lo = l + ( (FT_UInt32)m << 16 ); + hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l ); - ah = (FT_UInt32)( ( a >> 16 ) & 0xFFFFU ); - al = (FT_UInt32)( a & 0xFFFFU ); + /* divide the result by 2^14 with rounding */ + l = lo + 0x2000U + (FT_UInt32)( hi >> 31 ); /* rounding phase */ + hi += ( l < lo ); - lo = al * b; - mid = ah * b; - hi = mid >> 16; - mid = ( mid << 16 ) + ( 1 << 13 ); /* rounding */ - lo += mid; - if ( lo < mid ) - hi += 1; - - mid = ( lo >> 14 ) | ( hi << 18 ); - - return sign >= 0 ? (FT_Int32)mid : -(FT_Int32)mid; + return (FT_F26Dot6)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) ); } #endif /* !TT_MulFix14 */ -#if defined( __GNUC__ ) && \ - ( defined( __i386__ ) || \ - defined( __x86_64__ ) || \ - defined( __arm__ ) ) - -#define TT_DotFix14 TT_DotFix14_long_long - -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wlong-long" - - static __attribute__(( pure )) FT_Int32 - TT_DotFix14_long_long( FT_Int32 ax, - FT_Int32 ay, - FT_Int bx, - FT_Int by ) - { - /* Temporarily disable the warning that C90 doesn't support */ - /* `long long'. */ - - long long temp1 = (long long)ax * bx; - long long temp2 = (long long)ay * by; - - - temp1 += temp2; - temp2 = temp1 >> 63; - temp1 += 0x2000 + temp2; - - return (FT_Int32)( temp1 >> 14 ); - - } - -#if ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 406 -#pragma GCC diagnostic pop -#endif - -#endif /* __GNUC__ && (__arm__ || __i386__ || __x86_64__) */ - - -#ifndef TT_DotFix14 +#ifdef FT_INT64 /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */ - static FT_Int32 - TT_DotFix14( FT_Int32 ax, - FT_Int32 ay, - FT_Int bx, - FT_Int by ) + static inline FT_F26Dot6 + TT_DotFix14( FT_F26Dot6 ax, + FT_F26Dot6 ay, + FT_F2Dot14 bx, + FT_F2Dot14 by ) { - FT_Int32 m, s, hi1, hi2, hi; + FT_Int64 c = ADD_INT64( MUL_INT64( ax, bx ), MUL_INT64( ay, by ) ); + + + c = ADD_INT64( c, 0x2000 + ( c >> 63 ) ); /* rounding phase */ + + return (FT_F26Dot6)( c >> 14 ); + } + +#else + + static inline FT_F26Dot6 + TT_DotFix14( FT_F26Dot6 ax, + FT_F26Dot6 ay, + FT_F2Dot14 bx, + FT_F2Dot14 by ) + { + FT_Int32 m, hi1, hi2, hi; FT_UInt32 l, lo1, lo2, lo; - /* compute ax*bx as 64-bit value */ + /* compute ax*bx as 64-bit (hi_lo) value */ l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx ); m = ( ax >> 16 ) * bx; @@ -1366,18 +1233,13 @@ hi = hi1 + hi2 + ( lo < lo1 ); /* divide the result by 2^14 with rounding */ - s = hi >> 31; - l = lo + (FT_UInt32)s; - hi += s + ( l < lo ); - lo = l; - - l = lo + 0x2000U; + l = lo + 0x2000U + (FT_UInt32)( hi >> 31 ); /* rounding phase */ hi += ( l < lo ); - return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) ); + return (FT_F26Dot6)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) ); } -#endif /* TT_DotFix14 */ +#endif /* !FT_INT64 */ /************************************************************************** @@ -1531,31 +1393,6 @@ } - /************************************************************************** - * - * @Function: - * GetShortIns - * - * @Description: - * Returns a short integer taken from the instruction stream at - * address IP. - * - * @Return: - * Short read at code[IP]. - * - * @Note: - * This one could become a macro. - */ - static FT_Short - GetShortIns( TT_ExecContext exc ) - { - /* Reading a byte stream so there is no endianness (DaveP) */ - exc->IP += 2; - return (FT_Short)( ( exc->code[exc->IP - 2] << 8 ) + - exc->code[exc->IP - 1] ); - } - - /************************************************************************** * * @Function: @@ -1609,6 +1446,7 @@ exc->code = range->base; exc->codeSize = range->size; exc->IP = aIP; + exc->length = 0; exc->curRange = aRange; return SUCCESS; @@ -1671,48 +1509,33 @@ FT_UShort point, FT_F26Dot6 distance ) { - FT_F26Dot6 v; + FT_Fixed v; - v = exc->GS.freeVector.x; - + v = exc->moveVector.x; if ( v != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* Exception to the post-IUP curfew: Allow the x component of */ /* diagonal moves, but only post-IUP. DejaVu tries to adjust */ /* diagonal stems like on `Z' and `z' post-IUP. */ - if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) - zone->cur[point].x = ADD_LONG( zone->cur[point].x, - FT_MulDiv( distance, - v, - exc->F_dot_P ) ); - else + if ( !exc->backward_compatibility ) #endif - - if ( NO_SUBPIXEL_HINTING ) zone->cur[point].x = ADD_LONG( zone->cur[point].x, - FT_MulDiv( distance, - v, - exc->F_dot_P ) ); + FT_MulFix( distance, v ) ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } - v = exc->GS.freeVector.y; - + v = exc->moveVector.y; if ( v != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility && - exc->iupx_called && - exc->iupy_called ) ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( exc->backward_compatibility != 0x7 ) #endif zone->cur[point].y = ADD_LONG( zone->cur[point].y, - FT_MulDiv( distance, - v, - exc->F_dot_P ) ); + FT_MulFix( distance, v ) ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1745,24 +1568,20 @@ FT_UShort point, FT_F26Dot6 distance ) { - FT_F26Dot6 v; + FT_Fixed v; - v = exc->GS.freeVector.x; + v = exc->moveVector.x; if ( v != 0 ) zone->org[point].x = ADD_LONG( zone->org[point].x, - FT_MulDiv( distance, - v, - exc->F_dot_P ) ); + FT_MulFix( distance, v ) ); - v = exc->GS.freeVector.y; + v = exc->moveVector.y; if ( v != 0 ) zone->org[point].y = ADD_LONG( zone->org[point].y, - FT_MulDiv( distance, - v, - exc->F_dot_P ) ); + FT_MulFix( distance, v ) ); } @@ -1784,12 +1603,8 @@ FT_F26Dot6 distance ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( SUBPIXEL_HINTING_MINIMAL && !exc->backward_compatibility ) - zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); - else + if ( !exc->backward_compatibility ) #endif - - if ( NO_SUBPIXEL_HINTING ) zone->cur[point].x = ADD_LONG( zone->cur[point].x, distance ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; @@ -1805,9 +1620,8 @@ FT_UNUSED( exc ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility && - exc->iupx_called && exc->iupy_called ) ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( exc->backward_compatibility != 0x7 ) #endif zone->cur[point].y = ADD_LONG( zone->cur[point].y, distance ); @@ -1860,8 +1674,8 @@ * distance :: * The distance (not) to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * The compensated distance. @@ -1869,10 +1683,10 @@ static FT_F26Dot6 Round_None( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -1903,8 +1717,8 @@ * distance :: * The distance to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * Rounded distance. @@ -1912,10 +1726,10 @@ static FT_F26Dot6 Round_To_Grid( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -1948,8 +1762,8 @@ * distance :: * The distance to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * Rounded distance. @@ -1957,10 +1771,10 @@ static FT_F26Dot6 Round_To_Half_Grid( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -1995,8 +1809,8 @@ * distance :: * The distance to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * Rounded distance. @@ -2004,10 +1818,10 @@ static FT_F26Dot6 Round_Down_To_Grid( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -2039,8 +1853,8 @@ * distance :: * The distance to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * Rounded distance. @@ -2048,10 +1862,10 @@ static FT_F26Dot6 Round_Up_To_Grid( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -2084,8 +1898,8 @@ * distance :: * The distance to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * Rounded distance. @@ -2093,10 +1907,10 @@ static FT_F26Dot6 Round_To_Double_Grid( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; + FT_UNUSED( exc ); if ( distance >= 0 ) @@ -2129,8 +1943,8 @@ * distance :: * The distance to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * Rounded distance. @@ -2144,9 +1958,8 @@ static FT_F26Dot6 Round_Super( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; @@ -2185,8 +1998,8 @@ * distance :: * The distance to round. * - * color :: - * The engine compensation color. + * compensation :: + * The engine compensation. * * @Return: * Rounded distance. @@ -2198,9 +2011,8 @@ static FT_F26Dot6 Round_Super_45( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ) + FT_F26Dot6 compensation ) { - FT_F26Dot6 compensation = exc->tt_metrics.compensations[color]; FT_F26Dot6 val; @@ -2227,59 +2039,6 @@ } - /************************************************************************** - * - * @Function: - * Compute_Round - * - * @Description: - * Sets the rounding mode. - * - * @Input: - * round_mode :: - * The rounding mode to be used. - */ - static void - Compute_Round( TT_ExecContext exc, - FT_Byte round_mode ) - { - switch ( round_mode ) - { - case TT_Round_Off: - exc->func_round = (TT_Round_Func)Round_None; - break; - - case TT_Round_To_Grid: - exc->func_round = (TT_Round_Func)Round_To_Grid; - break; - - case TT_Round_Up_To_Grid: - exc->func_round = (TT_Round_Func)Round_Up_To_Grid; - break; - - case TT_Round_Down_To_Grid: - exc->func_round = (TT_Round_Func)Round_Down_To_Grid; - break; - - case TT_Round_To_Half_Grid: - exc->func_round = (TT_Round_Func)Round_To_Half_Grid; - break; - - case TT_Round_To_Double_Grid: - exc->func_round = (TT_Round_Func)Round_To_Double_Grid; - break; - - case TT_Round_Super: - exc->func_round = (TT_Round_Func)Round_Super; - break; - - case TT_Round_Super_45: - exc->func_round = (TT_Round_Func)Round_Super_45; - break; - } - } - - /************************************************************************** * * @Function: @@ -2481,14 +2240,45 @@ static void Compute_Funcs( TT_ExecContext exc ) { - if ( exc->GS.freeVector.x == 0x4000 ) - exc->F_dot_P = exc->GS.projVector.x; - else if ( exc->GS.freeVector.y == 0x4000 ) - exc->F_dot_P = exc->GS.projVector.y; + FT_Long F_dot_P = + ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x + + (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y + + 0x2000L ) >> 14; + + + if ( F_dot_P >= 0x3FFEL ) + { + /* commonly collinear */ + exc->moveVector.x = exc->GS.freeVector.x * 4; + exc->moveVector.y = exc->GS.freeVector.y * 4; + } + else if ( -0x400L < F_dot_P && F_dot_P < 0x400L ) + { + /* prohibitively orthogonal */ + exc->moveVector.x = 0; + exc->moveVector.y = 0; + } else - exc->F_dot_P = - ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x + - (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14; + { + exc->moveVector.x = exc->GS.freeVector.x * 0x10000L / F_dot_P; + exc->moveVector.y = exc->GS.freeVector.y * 0x10000L / F_dot_P; + } + + if ( F_dot_P >= 0x3FFEL && exc->GS.freeVector.x == 0x4000 ) + { + exc->func_move = (TT_Move_Func)Direct_Move_X; + exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X; + } + else if ( F_dot_P >= 0x3FFEL && exc->GS.freeVector.y == 0x4000 ) + { + exc->func_move = (TT_Move_Func)Direct_Move_Y; + exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y; + } + else + { + exc->func_move = (TT_Move_Func)Direct_Move; + exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig; + } if ( exc->GS.projVector.x == 0x4000 ) exc->func_project = (TT_Project_Func)Project_x; @@ -2504,29 +2294,6 @@ else exc->func_dualproj = (TT_Project_Func)Dual_Project; - exc->func_move = (TT_Move_Func)Direct_Move; - exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig; - - if ( exc->F_dot_P == 0x4000L ) - { - if ( exc->GS.freeVector.x == 0x4000 ) - { - exc->func_move = (TT_Move_Func)Direct_Move_X; - exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_X; - } - else if ( exc->GS.freeVector.y == 0x4000 ) - { - exc->func_move = (TT_Move_Func)Direct_Move_Y; - exc->func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y; - } - } - - /* at small sizes, F_dot_P can become too small, resulting */ - /* in overflows and `spikes' in a number of glyphs like `w'. */ - - if ( FT_ABS( exc->F_dot_P ) < 0x400L ) - exc->F_dot_P = 0x4000L; - /* Disable cached aspect ratio */ exc->tt_metrics.ratio = 0; } @@ -2799,7 +2566,7 @@ Ins_ODD( TT_ExecContext exc, FT_Long* args ) { - args[0] = ( ( exc->func_round( exc, args[0], 3 ) & 127 ) == 64 ); + args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 64 ) == 64 ); } @@ -2813,7 +2580,7 @@ Ins_EVEN( TT_ExecContext exc, FT_Long* args ) { - args[0] = ( ( exc->func_round( exc, args[0], 3 ) & 127 ) == 0 ); + args[0] = ( ( exc->func_round( exc, args[0], 0 ) & 64 ) == 0 ); } @@ -3020,7 +2787,7 @@ FT_MEM_QRENEW_ARRAY( exc->glyfStorage, exc->glyfStoreSize, exc->storeSize ); - exc->error = error; + exc->error = error; if ( error ) return; @@ -3143,7 +2910,8 @@ Ins_ROUND( TT_ExecContext exc, FT_Long* args ) { - args[0] = exc->func_round( exc, args[0], exc->opcode & 3 ); + args[0] = exc->func_round( exc, args[0], + exc->GS.compensation[exc->opcode & 3] ); } @@ -3157,7 +2925,8 @@ Ins_NROUND( TT_ExecContext exc, FT_Long* args ) { - args[0] = Round_None( exc, args[0], exc->opcode & 3 ); + args[0] = Round_None( exc, args[0], + exc->GS.compensation[exc->opcode & 3] ); } @@ -3211,13 +2980,11 @@ } else { - K = exc->stack[exc->args - L]; + K = args[-L]; - FT_ARRAY_MOVE( &exc->stack[exc->args - L ], - &exc->stack[exc->args - L + 1], - ( L - 1 ) ); + FT_ARRAY_MOVE( args - L, args - L + 1, L - 1 ); - exc->stack[exc->args - 1] = K; + args[-1] = K; } } @@ -3244,7 +3011,7 @@ args[0] = 0; } else - args[0] = exc->stack[exc->args - L]; + args[0] = args[-L]; } @@ -3314,8 +3081,7 @@ exc->length = 2 - exc->length * exc->code[exc->IP + 1]; } - if ( exc->IP + exc->length <= exc->codeSize ) - return SUCCESS; + return SUCCESS; } Fail_Overflow: @@ -3363,6 +3129,9 @@ nIfs--; Out = FT_BOOL( nIfs == 0 ); break; + + default: + break; } } while ( Out == 0 ); } @@ -3396,6 +3165,9 @@ case 0x59: /* EIF */ nIfs--; break; + + default: + break; } } while ( nIfs != 0 ); } @@ -3439,7 +3211,7 @@ return; } - exc->step_ins = FALSE; + exc->length = 0; if ( args[0] < 0 ) { @@ -3540,10 +3312,10 @@ return; } - rec->range = exc->curRange; - rec->opc = (FT_UInt16)n; - rec->start = exc->IP + 1; - rec->active = TRUE; + rec->range = exc->curRange; + rec->opc = (FT_UInt16)n; + rec->start = exc->IP + 1; + rec->active = TRUE; if ( n > exc->maxFunc ) exc->maxFunc = (FT_UInt16)n; @@ -3555,14 +3327,17 @@ { switch ( exc->opcode ) { - case 0x89: /* IDEF */ - case 0x2C: /* FDEF */ + case 0x89: /* IDEF */ + case 0x2C: /* FDEF */ exc->error = FT_THROW( Nested_DEFS ); return; case 0x2D: /* ENDF */ rec->end = exc->IP; return; + + default: + break; } } } @@ -3592,12 +3367,11 @@ pRec->Cur_Count--; - exc->step_ins = FALSE; - if ( pRec->Cur_Count > 0 ) { exc->callTop++; - exc->IP = pRec->Def->start; + exc->IP = pRec->Def->start; + exc->length = 0; } else /* Loop through the current function */ @@ -3685,8 +3459,6 @@ Ins_Goto_CodeRange( exc, def->range, def->start ); - exc->step_ins = FALSE; - return; Fail: @@ -3764,8 +3536,6 @@ Ins_Goto_CodeRange( exc, def->range, def->start ); - exc->step_ins = FALSE; - exc->loopcall_counter += (FT_ULong)args[0]; if ( exc->loopcall_counter > exc->loopcall_counter_max ) exc->error = FT_THROW( Execution_Too_Long ); @@ -3845,9 +3615,13 @@ case 0x2C: /* FDEF */ exc->error = FT_THROW( Nested_DEFS ); return; + case 0x2D: /* ENDF */ def->end = exc->IP; return; + + default: + break; } } } @@ -3870,10 +3644,23 @@ Ins_NPUSHB( TT_ExecContext exc, FT_Long* args ) { - FT_UShort L, K; + FT_Long IP = exc->IP; + FT_Int L, K; - L = (FT_UShort)exc->code[exc->IP + 1]; + if ( ++IP >= exc->codeSize ) + { + exc->error = FT_THROW( Code_Overflow ); + return; + } + + L = exc->code[IP]; + + if ( IP + L >= exc->codeSize ) + { + exc->error = FT_THROW( Code_Overflow ); + return; + } if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) { @@ -3881,10 +3668,11 @@ return; } - for ( K = 1; K <= L; K++ ) - args[K - 1] = exc->code[exc->IP + K + 1]; + for ( K = 0; K < L; K++ ) + args[K] = exc->code[++IP]; exc->new_top += L; + exc->IP = IP; } @@ -3898,10 +3686,23 @@ Ins_NPUSHW( TT_ExecContext exc, FT_Long* args ) { - FT_UShort L, K; + FT_Long IP = exc->IP; + FT_Int L, K; - L = (FT_UShort)exc->code[exc->IP + 1]; + if ( ++IP >= exc->codeSize ) + { + exc->error = FT_THROW( Code_Overflow ); + return; + } + + L = exc->code[IP]; + + if ( IP + 2 * L >= exc->codeSize ) + { + exc->error = FT_THROW( Code_Overflow ); + return; + } if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) { @@ -3909,13 +3710,12 @@ return; } - exc->IP += 2; + /* note casting for sign-extension */ + for ( K = 0; K < L; K++, IP += 2 ) + args[K] = (FT_Short)( exc->code[IP + 1] << 8 ) | exc->code[IP + 2]; - for ( K = 0; K < L; K++ ) - args[K] = GetShortIns( exc ); - - exc->step_ins = FALSE; exc->new_top += L; + exc->IP = IP; } @@ -3929,10 +3729,17 @@ Ins_PUSHB( TT_ExecContext exc, FT_Long* args ) { - FT_UShort L, K; + FT_Long IP = exc->IP; + FT_Int L, K; - L = (FT_UShort)( exc->opcode - 0xB0 + 1 ); + L = exc->opcode - 0xB0 + 1; + + if ( IP + L >= exc->codeSize ) + { + exc->error = FT_THROW( Code_Overflow ); + return; + } if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) { @@ -3940,8 +3747,10 @@ return; } - for ( K = 1; K <= L; K++ ) - args[K - 1] = exc->code[exc->IP + K]; + for ( K = 0; K < L; K++ ) + args[K] = exc->code[++IP]; + + exc->IP = IP; } @@ -3955,10 +3764,17 @@ Ins_PUSHW( TT_ExecContext exc, FT_Long* args ) { - FT_UShort L, K; + FT_Long IP = exc->IP; + FT_Int L, K; - L = (FT_UShort)( exc->opcode - 0xB8 + 1 ); + L = exc->opcode - 0xB8 + 1; + + if ( IP + 2 * L >= exc->codeSize ) + { + exc->error = FT_THROW( Code_Overflow ); + return; + } if ( BOUNDS( L, exc->stackSize + 1 - exc->top ) ) { @@ -3966,12 +3782,11 @@ return; } - exc->IP++; + /* note casting for sign-extension */ + for ( K = 0; K < L; K++, IP += 2 ) + args[K] = (FT_Short)( exc->code[IP + 1] << 8 ) | exc->code[IP + 2]; - for ( K = 0; K < L; K++ ) - args[K] = GetShortIns( exc ); - - exc->step_ins = FALSE; + exc->IP = IP; } @@ -4142,15 +3957,12 @@ Ins_SPVFS( TT_ExecContext exc, FT_Long* args ) { - FT_Short S; FT_Long X, Y; /* Only use low 16bits, then sign extend */ - S = (FT_Short)args[1]; - Y = (FT_Long)S; - S = (FT_Short)args[0]; - X = (FT_Long)S; + Y = (FT_Short)args[1]; + X = (FT_Short)args[0]; Normalize( X, Y, &exc->GS.projVector ); @@ -4169,15 +3981,12 @@ Ins_SFVFS( TT_ExecContext exc, FT_Long* args ) { - FT_Short S; FT_Long X, Y; /* Only use low 16bits, then sign extend */ - S = (FT_Short)args[1]; - Y = (FT_Long)S; - S = (FT_Short)args[0]; - X = S; + Y = (FT_Short)args[1]; + X = (FT_Short)args[0]; Normalize( X, Y, &exc->GS.freeVector ); Compute_Funcs( exc ); @@ -4915,7 +4724,7 @@ /* compatibility hacks and lets them program points to the grid like */ /* it's 1996. They might sign a waiver for just one glyph, though. */ if ( SUBPIXEL_HINTING_MINIMAL ) - exc->backward_compatibility = !FT_BOOL( L == 4 ); + exc->backward_compatibility = ( L & 4 ) ^ 4; #endif } else if ( exc->pedantic_hinting ) @@ -4999,32 +4808,31 @@ * Stack: uint32... --> */ static void - Ins_FLIPPT( TT_ExecContext exc ) + Ins_FLIPPT( TT_ExecContext exc, + FT_Long* args ) { + FT_Long loop = exc->GS.loop; FT_UShort point; -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backward compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility && - exc->iupx_called && - exc->iupy_called ) - goto Fail; -#endif - - if ( exc->top < exc->GS.loop ) + if ( exc->new_top < loop ) { if ( exc->pedantic_hinting ) exc->error = FT_THROW( Too_Few_Arguments ); goto Fail; } - while ( exc->GS.loop > 0 ) - { - exc->args--; + exc->new_top -= loop; - point = (FT_UShort)exc->stack[exc->args]; +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( exc->backward_compatibility == 0x7 ) + goto Fail; +#endif + + while ( loop-- ) + { + point = (FT_UShort)*(--args); if ( BOUNDS( point, exc->pts.n_points ) ) { @@ -5036,13 +4844,10 @@ } else exc->pts.tags[point] ^= FT_CURVE_TAG_ON; - - exc->GS.loop--; } Fail: exc->GS.loop = 1; - exc->new_top = exc->args; } @@ -5061,10 +4866,7 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* See `ttinterp.h' for details on backward compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility && - exc->iupx_called && - exc->iupy_called ) + if ( exc->backward_compatibility == 0x7 ) return; #endif @@ -5099,10 +4901,7 @@ #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL /* See `ttinterp.h' for details on backward compatibility mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility && - exc->iupx_called && - exc->iupy_called ) + if ( exc->backward_compatibility == 0x7 ) return; #endif @@ -5158,8 +4957,8 @@ d = PROJECT( zp.cur + p, zp.org + p ); - *x = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.x, exc->F_dot_P ); - *y = FT_MulDiv( d, (FT_Long)exc->GS.freeVector.y, exc->F_dot_P ); + *x = FT_MulFix( d, exc->moveVector.x ); + *y = FT_MulFix( d, exc->moveVector.y ); return SUCCESS; } @@ -5176,8 +4975,8 @@ if ( exc->GS.freeVector.x != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility ) ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( !exc->backward_compatibility ) #endif exc->zp2.cur[point].x = ADD_LONG( exc->zp2.cur[point].x, dx ); @@ -5188,10 +4987,8 @@ if ( exc->GS.freeVector.y != 0 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( !( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility && - exc->iupx_called && - exc->iupy_called ) ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( exc->backward_compatibility != 0x7 ) #endif exc->zp2.cur[point].y = ADD_LONG( exc->zp2.cur[point].y, dy ); @@ -5208,8 +5005,10 @@ * Stack: uint32... --> */ static void - Ins_SHP( TT_ExecContext exc ) + Ins_SHP( TT_ExecContext exc, + FT_Long* args ) { + FT_Long loop = exc->GS.loop; TT_GlyphZoneRec zp; FT_UShort refp; @@ -5217,20 +5016,21 @@ FT_UShort point; - if ( exc->top < exc->GS.loop ) + if ( exc->new_top < loop ) { if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); + exc->error = FT_THROW( Too_Few_Arguments ); goto Fail; } + exc->new_top -= loop; + if ( Compute_Point_Displacement( exc, &dx, &dy, &zp, &refp ) ) return; - while ( exc->GS.loop > 0 ) + while ( loop-- ) { - exc->args--; - point = (FT_UShort)exc->stack[exc->args]; + point = (FT_UShort)*(--args); if ( BOUNDS( point, exc->zp2.n_points ) ) { @@ -5242,13 +5042,10 @@ } else Move_Zp2_Point( exc, point, dx, dy, TRUE ); - - exc->GS.loop--; } Fail: exc->GS.loop = 1; - exc->new_top = exc->args; } @@ -5364,6 +5161,7 @@ Ins_SHPIX( TT_ExecContext exc, FT_Long* args ) { + FT_Long loop = exc->GS.loop; FT_F26Dot6 dx, dy; FT_UShort point; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL @@ -5373,22 +5171,21 @@ #endif - - if ( exc->top < exc->GS.loop + 1 ) + if ( exc->new_top < loop ) { if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); + exc->error = FT_THROW( Too_Few_Arguments ); goto Fail; } + exc->new_top -= loop; + dx = TT_MulFix14( args[0], exc->GS.freeVector.x ); dy = TT_MulFix14( args[0], exc->GS.freeVector.y ); - while ( exc->GS.loop > 0 ) + while ( loop-- ) { - exc->args--; - - point = (FT_UShort)exc->stack[exc->args]; + point = (FT_UShort)*(--args); if ( BOUNDS( point, exc->zp2.n_points ) ) { @@ -5400,8 +5197,7 @@ } else #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility ) + if ( exc->backward_compatibility ) { /* Special case: allow SHPIX to move points in the twilight zone. */ /* Otherwise, treat SHPIX the same as DELTAP. Unbreaks various */ @@ -5409,7 +5205,7 @@ /* that would glitch severely after calling ALIGNRP after a */ /* blocked SHPIX. */ if ( in_twilight || - ( !( exc->iupx_called && exc->iupy_called ) && + ( exc->backward_compatibility != 0x7 && ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || ( exc->zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y ) ) ) ) Move_Zp2_Point( exc, point, 0, dy, TRUE ); @@ -5417,13 +5213,10 @@ else #endif Move_Zp2_Point( exc, point, dx, dy, TRUE ); - - exc->GS.loop--; } Fail: exc->GS.loop = 1; - exc->new_top = exc->args; } @@ -5502,7 +5295,7 @@ if ( ( exc->opcode & 1 ) != 0 ) { cur_dist = FAST_PROJECT( &exc->zp0.cur[point] ); - distance = SUB_LONG( exc->func_round( exc, cur_dist, 3 ), cur_dist ); + distance = SUB_LONG( exc->func_round( exc, cur_dist, 0 ), cur_dist ); } else distance = 0; @@ -5566,7 +5359,7 @@ if ( exc->GS.gep0 == 0 ) /* If in twilight zone */ { exc->zp0.org[point].x = TT_MulFix14( distance, - exc->GS.freeVector.x ); + exc->GS.freeVector.x ); exc->zp0.org[point].y = TT_MulFix14( distance, exc->GS.freeVector.y ); exc->zp0.cur[point] = exc->zp0.org[point]; @@ -5587,7 +5380,7 @@ if ( delta > control_value_cutin ) distance = org_dist; - distance = exc->func_round( exc, distance, 3 ); + distance = exc->func_round( exc, distance, 0 ); } exc->func_move( exc, &exc->zp0, point, SUB_LONG( distance, org_dist ) ); @@ -5609,7 +5402,7 @@ FT_Long* args ) { FT_UShort point = 0; - FT_F26Dot6 org_dist, distance; + FT_F26Dot6 org_dist, distance, compensation; point = (FT_UShort)args[0]; @@ -5678,12 +5471,12 @@ /* round flag */ + compensation = exc->GS.compensation[exc->opcode & 3]; + if ( ( exc->opcode & 4 ) != 0 ) - { - distance = exc->func_round( exc, org_dist, exc->opcode & 3 ); - } + distance = exc->func_round( exc, org_dist, compensation ); else - distance = Round_None( exc, org_dist, exc->opcode & 3 ); + distance = Round_None( exc, org_dist, compensation ); /* minimum distance flag */ @@ -5735,7 +5528,8 @@ FT_F26Dot6 cvt_dist, distance, cur_dist, - org_dist; + org_dist, + compensation; FT_F26Dot6 delta; @@ -5801,6 +5595,8 @@ /* control value cut-in and round */ + compensation = exc->GS.compensation[exc->opcode & 3]; + if ( ( exc->opcode & 4 ) != 0 ) { /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */ @@ -5831,16 +5627,16 @@ cvt_dist = org_dist; } - distance = exc->func_round( exc, cvt_dist, exc->opcode & 3 ); + distance = exc->func_round( exc, cvt_dist, compensation ); } else - distance = Round_None( exc, cvt_dist, exc->opcode & 3 ); + distance = Round_None( exc, cvt_dist, compensation ); /* minimum distance test */ if ( ( exc->opcode & 8 ) != 0 ) { - FT_F26Dot6 minimum_distance = exc->GS.minimum_distance; + FT_F26Dot6 minimum_distance = exc->GS.minimum_distance; if ( org_dist >= 0 ) @@ -5862,11 +5658,10 @@ Fail: exc->GS.rp1 = exc->GS.rp0; + exc->GS.rp2 = point; if ( ( exc->opcode & 16 ) != 0 ) exc->GS.rp0 = point; - - exc->GS.rp2 = point; } @@ -5877,25 +5672,33 @@ * Stack: uint32 uint32... --> */ static void - Ins_ALIGNRP( TT_ExecContext exc ) + Ins_ALIGNRP( TT_ExecContext exc, + FT_Long* args ) { + FT_Long loop = exc->GS.loop; FT_UShort point; FT_F26Dot6 distance; - if ( exc->top < exc->GS.loop || - BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) + if ( exc->new_top < loop ) + { + if ( exc->pedantic_hinting ) + exc->error = FT_THROW( Too_Few_Arguments ); + goto Fail; + } + + exc->new_top -= loop; + + if ( BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) { if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); goto Fail; } - while ( exc->GS.loop > 0 ) + while ( loop-- ) { - exc->args--; - - point = (FT_UShort)exc->stack[exc->args]; + point = (FT_UShort)*(--args); if ( BOUNDS( point, exc->zp1.n_points ) ) { @@ -5912,13 +5715,10 @@ exc->func_move( exc, &exc->zp1, point, NEG_LONG( distance ) ); } - - exc->GS.loop--; } Fail: exc->GS.loop = 1; - exc->new_top = exc->args; } @@ -6060,15 +5860,26 @@ /* SOMETIMES, DUMBER CODE IS BETTER CODE */ static void - Ins_IP( TT_ExecContext exc ) + Ins_IP( TT_ExecContext exc, + FT_Long* args ) { + FT_Long loop = exc->GS.loop; FT_F26Dot6 old_range, cur_range; FT_Vector* orus_base; FT_Vector* cur_base; FT_Int twilight; - if ( exc->top < exc->GS.loop ) + if ( exc->new_top < loop ) + { + if ( exc->pedantic_hinting ) + exc->error = FT_THROW( Too_Few_Arguments ); + goto Fail; + } + + exc->new_top -= loop; + + if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ) { if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); @@ -6084,13 +5895,6 @@ exc->GS.gep1 == 0 || exc->GS.gep2 == 0 ); - if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); - goto Fail; - } - if ( twilight ) orus_base = &exc->zp0.org[exc->GS.rp1]; else @@ -6102,8 +5906,7 @@ /* fonts out there (e.g. [aeu]grave in monotype.ttf) */ /* calling IP[] with bad values of rp[12]. */ /* Do something sane when this odd thing happens. */ - if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) || - BOUNDS( exc->GS.rp2, exc->zp1.n_points ) ) + if ( BOUNDS( exc->GS.rp2, exc->zp1.n_points ) ) { old_range = 0; cur_range = 0; @@ -6132,9 +5935,9 @@ cur_range = PROJECT( &exc->zp1.cur[exc->GS.rp2], cur_base ); } - for ( ; exc->GS.loop > 0; exc->GS.loop-- ) + while ( loop-- ) { - FT_UInt point = (FT_UInt)exc->stack[--exc->args]; + FT_UInt point = (FT_UInt)*(--args); FT_F26Dot6 org_dist, cur_dist, new_dist; @@ -6206,7 +6009,6 @@ Fail: exc->GS.loop = 1; - exc->new_top = exc->args; } @@ -6405,17 +6207,10 @@ /* See `ttinterp.h' for details on backward compatibility mode. */ /* Allow IUP until it has been called on both axes. Immediately */ /* return on subsequent ones. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility ) - { - if ( exc->iupx_called && exc->iupy_called ) - return; - - if ( exc->opcode & 1 ) - exc->iupx_called = TRUE; - else - exc->iupy_called = TRUE; - } + if ( exc->backward_compatibility == 0x7 ) + return; + else if ( exc->backward_compatibility ) + exc->backward_compatibility |= 1 << ( exc->opcode & 1 ); #endif /* ignore empty outlines */ @@ -6507,30 +6302,50 @@ Ins_DELTAP( TT_ExecContext exc, FT_Long* args ) { - FT_ULong nump, k; + FT_Long nump; FT_UShort A; - FT_ULong C, P; - FT_Long B; + FT_Long B, P, F; - P = (FT_ULong)exc->func_cur_ppem( exc ); - nump = (FT_ULong)args[0]; /* some points theoretically may occur more - than once, thus UShort isn't enough */ + nump = args[0]; /* signed value for convenience */ - for ( k = 1; k <= nump; k++ ) + if ( nump < 0 || nump > exc->new_top / 2 ) { - if ( exc->args < 2 ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - exc->args = 0; - goto Fail; - } + if ( exc->pedantic_hinting ) + exc->error = FT_THROW( Too_Few_Arguments ); - exc->args -= 2; + nump = exc->new_top / 2; + } - A = (FT_UShort)exc->stack[exc->args + 1]; - B = exc->stack[exc->args]; + exc->new_top -= 2 * nump; + + P = exc->func_cur_ppem( exc ) - exc->GS.delta_base; + + switch ( exc->opcode ) + { + case 0x5D: + break; + + case 0x71: + P -= 16; + break; + + case 0x72: + P -= 32; + break; + } + + /* check applicable range of adjusted ppem */ + if ( P & ~0xF ) /* P < 0 || P > 15 */ + return; + + P <<= 4; + F = 1L << ( 6 - exc->GS.delta_shift ); + + while ( nump-- ) + { + A = (FT_UShort)*(--args); + B = *(--args); /* XXX: Because some popular fonts contain some invalid DeltaP */ /* instructions, we simply ignore them when the stacked */ @@ -6538,41 +6353,28 @@ /* error. As a delta instruction doesn't change a glyph */ /* in great ways, this shouldn't be a problem. */ - if ( !BOUNDS( A, exc->zp0.n_points ) ) + if ( BOUNDS( A, exc->zp0.n_points ) ) { - C = ( (FT_ULong)B & 0xF0 ) >> 4; - - switch ( exc->opcode ) + if ( exc->pedantic_hinting ) { - case 0x5D: - break; - - case 0x71: - C += 16; - break; - - case 0x72: - C += 32; - break; + exc->error = FT_THROW( Invalid_Reference ); + return; } - - C += exc->GS.delta_base; - - if ( P == C ) + } + else + { + if ( ( B & 0xF0 ) == P ) { - B = ( (FT_ULong)B & 0xF ) - 8; + B = ( B & 0xF ) - 8; if ( B >= 0 ) B++; - B *= 1L << ( 6 - exc->GS.delta_shift ); - + B *= F; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - /* See `ttinterp.h' for details on backward compatibility */ - /* mode. */ - if ( SUBPIXEL_HINTING_MINIMAL && - exc->backward_compatibility ) + /* See `ttinterp.h' for details on backward compatibility mode. */ + if ( exc->backward_compatibility ) { - if ( !( exc->iupx_called && exc->iupy_called ) && + if ( exc->backward_compatibility != 0x7 && ( ( exc->is_composite && exc->GS.freeVector.y != 0 ) || ( exc->zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) ) ) exc->func_move( exc, &exc->zp0, A, B ); @@ -6582,13 +6384,7 @@ exc->func_move( exc, &exc->zp0, A, B ); } } - else - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Invalid_Reference ); } - - Fail: - exc->new_top = exc->args; } @@ -6602,28 +6398,50 @@ Ins_DELTAC( TT_ExecContext exc, FT_Long* args ) { - FT_ULong nump, k; - FT_ULong A, C, P; - FT_Long B; + FT_Long nump; + FT_ULong A; + FT_Long B, P, F; - P = (FT_ULong)exc->func_cur_ppem( exc ); - nump = (FT_ULong)args[0]; + nump = args[0]; /* signed value for convenience */ - for ( k = 1; k <= nump; k++ ) + if ( nump < 0 || nump > exc->new_top / 2 ) { - if ( exc->args < 2 ) - { - if ( exc->pedantic_hinting ) - exc->error = FT_THROW( Too_Few_Arguments ); - exc->args = 0; - goto Fail; - } + if ( exc->pedantic_hinting ) + exc->error = FT_THROW( Too_Few_Arguments ); - exc->args -= 2; + nump = exc->new_top / 2; + } - A = (FT_ULong)exc->stack[exc->args + 1]; - B = exc->stack[exc->args]; + exc->new_top -= 2 * nump; + + P = exc->func_cur_ppem( exc ) - exc->GS.delta_base; + + switch ( exc->opcode ) + { + case 0x73: + break; + + case 0x74: + P -= 16; + break; + + case 0x75: + P -= 32; + break; + } + + /* check applicable range of adjusted ppem */ + if ( P & ~0xF ) /* P < 0 || P > 15 */ + return; + + P <<= 4; + F = 1L << ( 6 - exc->GS.delta_shift ); + + while ( nump-- ) + { + A = (FT_ULong)*(--args); + B = *(--args); if ( BOUNDSL( A, exc->cvtSize ) ) { @@ -6635,38 +6453,17 @@ } else { - C = ( (FT_ULong)B & 0xF0 ) >> 4; - - switch ( exc->opcode ) + if ( ( B & 0xF0 ) == P ) { - case 0x73: - break; - - case 0x74: - C += 16; - break; - - case 0x75: - C += 32; - break; - } - - C += exc->GS.delta_base; - - if ( P == C ) - { - B = ( (FT_ULong)B & 0xF ) - 8; + B = ( B & 0xF ) - 8; if ( B >= 0 ) B++; - B *= 1L << ( 6 - exc->GS.delta_shift ); + B *= F; exc->func_move_cvt( exc, A, B ); } } } - - Fail: - exc->new_top = exc->args; } @@ -6736,7 +6533,7 @@ /* Otherwise, instructions may behave weirdly and rendering results */ /* may differ between v35 and v40 mode, e.g., in `Times New Roman */ /* Bold Italic'. */ - if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean ) + if ( SUBPIXEL_HINTING_MINIMAL && exc->mode != FT_RENDER_MODE_MONO ) { /********************************* * HINTING FOR SUBPIXEL @@ -6753,7 +6550,7 @@ * Selector Bit: 8 * Return Bit(s): 15 */ - if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean ) + if ( ( args[0] & 256 ) != 0 && exc->mode == FT_RENDER_MODE_LCD_V ) K |= 1 << 15; /********************************* @@ -6774,7 +6571,7 @@ * The only smoothing method FreeType supports unless someone sets * FT_LOAD_TARGET_MONO. */ - if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean ) + if ( ( args[0] & 2048 ) != 0 && exc->mode != FT_RENDER_MODE_MONO ) K |= 1 << 18; /********************************* @@ -6786,7 +6583,10 @@ * Grayscale rendering is what FreeType does anyway unless someone * sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V) */ - if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype ) + if ( ( args[0] & 4096 ) != 0 && + exc->mode != FT_RENDER_MODE_MONO && + exc->mode != FT_RENDER_MODE_LCD && + exc->mode != FT_RENDER_MODE_LCD_V ) K |= 1 << 19; } #endif @@ -6833,6 +6633,8 @@ for ( i = 0; i < num_axes; i++ ) args[i] = 0; } + + exc->new_top += num_axes; } @@ -6883,7 +6685,6 @@ Ins_Goto_CodeRange( exc, def->range, def->start ); - exc->step_ins = FALSE; return; } } @@ -6928,96 +6729,22 @@ TT_RunIns( void* exec ) { TT_ExecContext exc = (TT_ExecContext)exec; + FT_ULong ins_counter = 0; - FT_ULong ins_counter = 0; /* executed instructions counter */ - FT_ULong num_twilight_points; - FT_UShort i; - - - /* We restrict the number of twilight points to a reasonable, */ - /* heuristic value to avoid slow execution of malformed bytecode. */ - num_twilight_points = FT_MAX( 30, - 2 * ( exc->pts.n_points + exc->cvtSize ) ); - if ( exc->twilight.n_points > num_twilight_points ) - { - if ( num_twilight_points > 0xFFFFU ) - num_twilight_points = 0xFFFFU; - - FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n" )); - FT_TRACE5(( " from %d to the more reasonable value %ld\n", - exc->twilight.n_points, - num_twilight_points )); - exc->twilight.n_points = (FT_UShort)num_twilight_points; - } - - /* Set up loop detectors. We restrict the number of LOOPCALL loops */ - /* and the number of JMPR, JROT, and JROF calls with a negative */ - /* argument to values that depend on various parameters like the */ - /* size of the CVT table or the number of points in the current */ - /* glyph (if applicable). */ - /* */ - /* The idea is that in real-world bytecode you either iterate over */ - /* all CVT entries (in the `prep' table), or over all points (or */ - /* contours, in the `glyf' table) of a glyph, and such iterations */ - /* don't happen very often. */ - exc->loopcall_counter = 0; - exc->neg_jump_counter = 0; - - /* The maximum values are heuristic. */ - if ( exc->pts.n_points ) - exc->loopcall_counter_max = FT_MAX( 50, - 10 * exc->pts.n_points ) + - FT_MAX( 50, - exc->cvtSize / 10 ); - else - exc->loopcall_counter_max = 300 + 22 * exc->cvtSize; - - /* as a protection against an unreasonable number of CVT entries */ - /* we assume at most 100 control values per glyph for the counter */ - if ( exc->loopcall_counter_max > - 100 * (FT_ULong)exc->face->root.num_glyphs ) - exc->loopcall_counter_max = 100 * (FT_ULong)exc->face->root.num_glyphs; - - FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL" - " to %ld\n", exc->loopcall_counter_max )); - - exc->neg_jump_counter_max = exc->loopcall_counter_max; - FT_TRACE5(( "TT_RunIns: Limiting total number of backward jumps" - " to %ld\n", exc->neg_jump_counter_max )); - - /* set PPEM and CVT functions */ - exc->tt_metrics.ratio = 0; - if ( exc->metrics.x_ppem != exc->metrics.y_ppem ) - { - /* non-square pixels, use the stretched routines */ - exc->func_cur_ppem = Current_Ppem_Stretched; - exc->func_read_cvt = Read_CVT_Stretched; - exc->func_write_cvt = Write_CVT_Stretched; - exc->func_move_cvt = Move_CVT_Stretched; - } - else - { - /* square pixels, use normal routines */ - exc->func_cur_ppem = Current_Ppem; - exc->func_read_cvt = Read_CVT; - exc->func_write_cvt = Write_CVT; - exc->func_move_cvt = Move_CVT; - } - - exc->iniRange = exc->curRange; - - Compute_Funcs( exc ); - Compute_Round( exc, (FT_Byte)exc->GS.round_state ); - - /* These flags cancel execution of some opcodes after IUP is called */ -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL - exc->iupx_called = FALSE; - exc->iupy_called = FALSE; -#endif do { + /* increment instruction counter and check if we didn't */ + /* run this program for too long (e.g. infinite loops). */ + if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES ) + { + exc->error = FT_THROW( Execution_Too_Long ); + goto LErrorLabel_; + } + + exc->error = FT_Err_Ok; exc->opcode = exc->code[exc->IP]; + exc->length = 1; #ifdef FT_DEBUG_LEVEL_TRACE if ( ft_trace_levels[trace_ttinterp] >= 6 ) @@ -7041,17 +6768,6 @@ } #endif /* FT_DEBUG_LEVEL_TRACE */ - if ( ( exc->length = opcode_length[exc->opcode] ) < 0 ) - { - if ( exc->IP + 1 >= exc->codeSize ) - goto LErrorCodeOverflow_; - - exc->length = 2 - exc->length * exc->code[exc->IP + 1]; - } - - if ( exc->IP + exc->length > exc->codeSize ) - goto LErrorCodeOverflow_; - /* First, let's check for empty stack and overflow */ exc->args = exc->top - ( Pop_Push_Count[exc->opcode] >> 4 ); @@ -7059,6 +6775,9 @@ /* One can also interpret it as the index of the last argument. */ if ( exc->args < 0 ) { + FT_UShort i; + + if ( exc->pedantic_hinting ) { exc->error = FT_THROW( Too_Few_Arguments ); @@ -7071,21 +6790,7 @@ exc->args = 0; } -#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT - if ( exc->opcode == 0x91 ) - { - /* this is very special: GETVARIATION returns */ - /* a variable number of arguments */ - - /* it is the job of the application to `activate' GX handling, */ - /* that is, calling any of the GX API functions on the current */ - /* font to select a variation instance */ - if ( exc->face->blend ) - exc->new_top = exc->args + exc->face->blend->num_axis; - } - else -#endif - exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 ); + exc->new_top = exc->args + ( Pop_Push_Count[exc->opcode] & 15 ); /* `new_top' is the new top of the stack, after the instruction's */ /* execution. `top' will be set to `new_top' after the `switch' */ @@ -7096,9 +6801,6 @@ goto LErrorLabel_; } - exc->step_ins = TRUE; - exc->error = FT_Err_Ok; - { FT_Long* args = exc->stack + exc->args; FT_Byte opcode = exc->opcode; @@ -7281,7 +6983,7 @@ case 0x32: /* SHP */ case 0x33: /* SHP */ - Ins_SHP( exc ); + Ins_SHP( exc, args ); break; case 0x34: /* SHC */ @@ -7299,7 +7001,7 @@ break; case 0x39: /* IP */ - Ins_IP( exc ); + Ins_IP( exc, args ); break; case 0x3A: /* MSIRP */ @@ -7308,7 +7010,7 @@ break; case 0x3C: /* AlignRP */ - Ins_ALIGNRP( exc ); + Ins_ALIGNRP( exc, args ); break; case 0x3D: /* RTDG */ @@ -7544,7 +7246,7 @@ break; case 0x80: /* FLIPPT */ - Ins_FLIPPT( exc ); + Ins_FLIPPT( exc, args ); break; case 0x81: /* FLIPRGON */ @@ -7642,13 +7344,13 @@ { switch ( exc->error ) { - /* looking for redefined instructions */ case FT_ERR( Invalid_Opcode ): { TT_DefRecord* def = exc->IDefs; TT_DefRecord* limit = FT_OFFSET( def, exc->numIDefs ); + /* looking for redefined instructions */ for ( ; def < limit; def++ ) { if ( def->active && exc->opcode == (FT_Byte)def->opc ) @@ -7678,37 +7380,15 @@ } } } - - exc->error = FT_THROW( Invalid_Opcode ); - goto LErrorLabel_; - -#if 0 - break; /* Unreachable code warning suppression. */ - /* Leave to remind in case a later change the editor */ - /* to consider break; */ -#endif + FALL_THROUGH; default: goto LErrorLabel_; - -#if 0 - break; -#endif } } exc->top = exc->new_top; - - if ( exc->step_ins ) - exc->IP += exc->length; - - /* increment instruction counter and check if we didn't */ - /* run this program for too long (e.g. infinite loops). */ - if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES ) - { - exc->error = FT_THROW( Execution_Too_Long ); - goto LErrorLabel_; - } + exc->IP += exc->length; LSuiteLabel_: if ( exc->IP >= exc->codeSize ) @@ -7724,15 +7404,12 @@ } while ( !exc->instruction_trap ); LNo_Error_: - FT_TRACE4(( " %ld instruction%s executed\n", + FT_TRACE4(( " %lu instruction%s executed\n", ins_counter, ins_counter == 1 ? "" : "s" )); return FT_Err_Ok; - LErrorCodeOverflow_: - exc->error = FT_THROW( Code_Overflow ); - LErrorLabel_: if ( exc->error && !exc->instruction_trap ) FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error )); @@ -7740,6 +7417,126 @@ return exc->error; } + + /************************************************************************** + * + * @Function: + * TT_Run_Context + * + * @Description: + * Executes one or more instructions in the execution context. + * + * @Input: + * exec :: + * A handle to the target execution context. + * + * @Return: + * TrueType error code. 0 means success. + */ + FT_LOCAL_DEF( FT_Error ) + TT_Run_Context( TT_ExecContext exec, + TT_Size size ) + { + FT_ULong num_twilight_points; + + + exec->zp0 = exec->pts; + exec->zp1 = exec->pts; + exec->zp2 = exec->pts; + + /* We restrict the number of twilight points to a reasonable, */ + /* heuristic value to avoid slow execution of malformed bytecode. */ + /* The selected value is large enough to support fonts hinted */ + /* with `ttfautohint`, which uses twilight points to store */ + /* vertical coordinates of (auto-hinter) segments. */ + num_twilight_points = FT_MAX( 30, + 2 * ( exec->pts.n_points + exec->cvtSize ) ); + if ( exec->twilight.n_points > num_twilight_points ) + { + if ( num_twilight_points > 0xFFFFU ) + num_twilight_points = 0xFFFFU; + + FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n" )); + FT_TRACE5(( " from %d to the more reasonable value %lu\n", + exec->twilight.n_points, + num_twilight_points )); + exec->twilight.n_points = (FT_UShort)num_twilight_points; + } + + /* Set up loop detectors. We restrict the number of LOOPCALL loops */ + /* and the number of JMPR, JROT, and JROF calls with a negative */ + /* argument to values that depend on various parameters like the */ + /* size of the CVT table or the number of points in the current */ + /* glyph (if applicable). */ + /* */ + /* The idea is that in real-world bytecode you either iterate over */ + /* all CVT entries (in the `prep' table), or over all points (or */ + /* contours, in the `glyf' table) of a glyph, and such iterations */ + /* don't happen very often. */ + exec->loopcall_counter = 0; + exec->neg_jump_counter = 0; + + /* The maximum values are heuristic. */ + if ( exec->pts.n_points ) + exec->loopcall_counter_max = FT_MAX( 50, + 10 * exec->pts.n_points ) + + FT_MAX( 50, + exec->cvtSize / 10 ); + else + exec->loopcall_counter_max = 300 + 22 * exec->cvtSize; + + /* as a protection against an unreasonable number of CVT entries */ + /* we assume at most 100 control values per glyph for the counter */ + if ( exec->loopcall_counter_max > + 100 * (FT_ULong)exec->face->root.num_glyphs ) + exec->loopcall_counter_max = 100 * (FT_ULong)exec->face->root.num_glyphs; + + FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL" + " to %lu\n", exec->loopcall_counter_max )); + + exec->neg_jump_counter_max = exec->loopcall_counter_max; + FT_TRACE5(( "TT_RunIns: Limiting total number of backward jumps" + " to %lu\n", exec->neg_jump_counter_max )); + + /* set PPEM and CVT functions */ + if ( exec->metrics.x_ppem != exec->metrics.y_ppem ) + { + /* non-square pixels, use the stretched routines */ + exec->func_cur_ppem = Current_Ppem_Stretched; + exec->func_read_cvt = Read_CVT_Stretched; + exec->func_write_cvt = Write_CVT_Stretched; + exec->func_move_cvt = Move_CVT_Stretched; + } + else + { + /* square pixels, use normal routines */ + exec->func_cur_ppem = Current_Ppem; + exec->func_read_cvt = Read_CVT; + exec->func_write_cvt = Write_CVT; + exec->func_move_cvt = Move_CVT; + } + + /* reset graphics state */ + exec->GS = size->GS; + exec->func_round = (TT_Round_Func)Round_To_Grid; + Compute_Funcs( exec ); + +#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* Reset IUP tracking bits in the backward compatibility mode. */ + /* See `ttinterp.h' for details. */ + exec->backward_compatibility &= ~0x3; +#endif + + /* some glyphs leave something on the stack, */ + /* so we clean it before a new execution. */ + exec->top = 0; + exec->callTop = 0; + + exec->instruction_trap = FALSE; + + return exec->interpreter( exec ); + } + #else /* !TT_USE_BYTECODE_INTERPRETER */ /* ANSI C doesn't like empty source files */ diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h index 4f1a9bbc679..2e69d191890 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h @@ -4,7 +4,7 @@ * * TrueType bytecode interpreter (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -39,6 +39,60 @@ FT_BEGIN_HEADER #define TT_Round_Super_45 7 + /************************************************************************** + * + * EXECUTION SUBTABLES + * + * These sub-tables relate to instruction execution. + * + */ + + +#define TT_MAX_CODE_RANGES 3 + + + /************************************************************************** + * + * There can only be 3 active code ranges at once: + * - the Font Program + * - the CVT Program + * - a glyph's instructions set + */ + typedef enum TT_CodeRange_Tag_ + { + tt_coderange_none = 0, + tt_coderange_font, + tt_coderange_cvt, + tt_coderange_glyph + + } TT_CodeRange_Tag; + + + typedef struct TT_CodeRange_ + { + FT_Byte* base; + FT_Long size; + + } TT_CodeRange; + + typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES]; + + + /************************************************************************** + * + * Defines a function/instruction definition record. + */ + typedef struct TT_DefRecord_ + { + FT_Int range; /* in which code range is it located? */ + FT_Long start; /* where does it start? */ + FT_Long end; /* where does it end? */ + FT_UInt opc; /* function #, or instruction code */ + FT_Bool active; /* is it active? */ + + } TT_DefRecord, *TT_DefArray; + + /************************************************************************** * * Function types used by the interpreter, depending on various modes @@ -51,7 +105,7 @@ FT_BEGIN_HEADER typedef FT_F26Dot6 (*TT_Round_Func)( TT_ExecContext exc, FT_F26Dot6 distance, - FT_Int color ); + FT_F26Dot6 compensation ); /* Point displacement along the freedom vector routine */ typedef void @@ -111,12 +165,13 @@ FT_BEGIN_HEADER TT_Face face; /* ! */ TT_Size size; /* ! */ FT_Memory memory; + TT_Interpreter interpreter; /* instructions state */ FT_Error error; /* last execution error */ - FT_Long top; /* @ top of exec. stack */ + FT_Long top; /* @! top of exec. stack */ FT_Long stackSize; /* ! size of exec. stack */ FT_Long* stack; /* ! current exec. stack */ @@ -142,11 +197,9 @@ FT_BEGIN_HEADER FT_Long IP; /* current instruction pointer */ FT_Long codeSize; /* size of current range */ - FT_Byte opcode; /* current opcode */ - FT_Int length; /* length of current opcode */ + FT_Byte opcode; /* current opcode */ + FT_Int length; /* opcode length or increment */ - FT_Bool step_ins; /* true if the interpreter must */ - /* increment IP after ins. exec */ FT_ULong cvtSize; /* ! */ FT_Long* cvt; /* ! */ FT_ULong glyfCvtSize; @@ -166,9 +219,9 @@ FT_BEGIN_HEADER FT_UInt maxFunc; /* ! maximum function index */ FT_UInt maxIns; /* ! maximum instruction index */ - FT_Int callTop, /* @ top of call stack during execution */ - callSize; /* size of call stack */ - TT_CallStack callStack; /* call stack */ + FT_Int callTop, /* @! top of call stack during execution */ + callSize; /* size of call stack */ + TT_CallStack callStack; /* call stack */ FT_UShort maxPoints; /* capacity of this context's `pts' */ FT_Short maxContours; /* record, expressed in points and */ @@ -189,16 +242,14 @@ FT_BEGIN_HEADER FT_Bool instruction_trap; /* ! If `True', the interpreter */ /* exits after each instruction */ - TT_GraphicsState default_GS; /* graphics state resulting from */ - /* the prep program */ FT_Bool is_composite; /* true if the glyph is composite */ FT_Bool pedantic_hinting; /* true if pedantic interpretation */ /* latest interpreter additions */ - FT_Long F_dot_P; /* dot product of freedom and projection */ - /* vectors */ - TT_Round_Func func_round; /* current rounding function */ + TT_Round_Func func_round; /* current rounding function */ + + FT_Vector moveVector; /* "projected" freedom vector */ TT_Project_Func func_project, /* current projection function */ func_dualproj, /* current dual proj. function */ @@ -327,34 +378,13 @@ FT_BEGIN_HEADER * */ - /* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO has been - * requested. Used to detect interpreter */ - /* version switches. `_lean' to differentiate from the Infinality */ - /* `subpixel_hinting', which is managed differently. */ - FT_Bool subpixel_hinting_lean; + /* Activate backward compatibility (bit 2) and track IUP (bits 0-1). */ + /* If this is zero, it means that the interpreter is either in v35 */ + /* or in native ClearType mode. */ + FT_Int backward_compatibility; - /* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */ - /* `_lean' to differentiate from the Infinality `vertical_lcd', which */ - /* is managed differently. */ - FT_Bool vertical_lcd_lean; + FT_Render_Mode mode; /* target render mode */ - /* Default to backward compatibility mode in v40 interpreter. If */ - /* this is false, it implies the interpreter is in v35 or in native */ - /* ClearType mode. */ - FT_Bool backward_compatibility; - - /* Useful for detecting and denying post-IUP trickery that is usually */ - /* used to fix pixel patterns (`superhinting'). */ - FT_Bool iupx_called; - FT_Bool iupy_called; - - /* ClearType hinting and grayscale rendering, as used by Universal */ - /* Windows Platform apps (Windows 8 and above). Like the standard */ - /* colorful ClearType mode, it utilizes a vastly increased virtual */ - /* resolution on the x axis. Different from bi-level hinting and */ - /* grayscale rendering, the old mode from Win9x days that roughly */ - /* adheres to the physical pixel grid on both axes. */ - FT_Bool grayscale_cleartype; #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ /* We maintain two counters (in addition to the instruction counter) */ @@ -371,22 +401,15 @@ FT_BEGIN_HEADER extern const TT_GraphicsState tt_default_graphics_state; -#ifdef TT_USE_BYTECODE_INTERPRETER - FT_LOCAL( void ) - TT_Goto_CodeRange( TT_ExecContext exec, - FT_Int range, - FT_Long IP ); - FT_LOCAL( void ) TT_Set_CodeRange( TT_ExecContext exec, FT_Int range, - void* base, + FT_Byte* base, FT_Long length ); FT_LOCAL( void ) TT_Clear_CodeRange( TT_ExecContext exec, FT_Int range ); -#endif /* TT_USE_BYTECODE_INTERPRETER */ /************************************************************************** @@ -413,7 +436,6 @@ FT_BEGIN_HEADER TT_New_Context( TT_Driver driver ); -#ifdef TT_USE_BYTECODE_INTERPRETER FT_LOCAL( void ) TT_Done_Context( TT_ExecContext exec ); @@ -424,11 +446,11 @@ FT_BEGIN_HEADER FT_LOCAL( void ) TT_Save_Context( TT_ExecContext exec, - TT_Size ins ); + TT_Size size ); FT_LOCAL( FT_Error ) - TT_Run_Context( TT_ExecContext exec ); -#endif /* TT_USE_BYTECODE_INTERPRETER */ + TT_Run_Context( TT_ExecContext exec, + TT_Size size ); /************************************************************************** diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c index d0ac3181204..fd0c0ad14f6 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c @@ -4,7 +4,7 @@ * * Objects manager (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -67,23 +67,13 @@ * A pointer to the target glyph zone. */ FT_LOCAL_DEF( void ) - tt_glyphzone_done( TT_GlyphZone zone ) + tt_glyphzone_done( FT_Memory memory, + TT_GlyphZone zone ) { - FT_Memory memory = zone->memory; + FT_FREE( zone->org ); - - if ( memory ) - { - FT_FREE( zone->contours ); - FT_FREE( zone->tags ); - FT_FREE( zone->cur ); - FT_FREE( zone->org ); - FT_FREE( zone->orus ); - - zone->max_points = zone->n_points = 0; - zone->max_contours = zone->n_contours = 0; - zone->memory = NULL; - } + zone->n_points = 0; + zone->n_contours = 0; } @@ -119,23 +109,22 @@ TT_GlyphZone zone ) { FT_Error error; + FT_Long size = 3 * maxPoints * sizeof ( FT_Vector ) + + maxContours * sizeof ( FT_UShort ) + + maxPoints * sizeof ( FT_Byte ); - FT_ZERO( zone ); - zone->memory = memory; - - if ( FT_NEW_ARRAY( zone->org, maxPoints ) || - FT_NEW_ARRAY( zone->cur, maxPoints ) || - FT_NEW_ARRAY( zone->orus, maxPoints ) || - FT_NEW_ARRAY( zone->tags, maxPoints ) || - FT_NEW_ARRAY( zone->contours, maxContours ) ) + if ( !FT_ALLOC( zone->org, size ) ) { - tt_glyphzone_done( zone ); - } - else - { - zone->max_points = maxPoints; - zone->max_contours = maxContours; + zone->n_points = maxPoints; + zone->n_contours = maxContours; + + zone->cur = zone->org + maxPoints; + zone->orus = zone->cur + maxPoints; + zone->contours = (FT_UShort*)( zone->orus + maxPoints ); + zone->tags = (FT_Byte*)( zone->contours + maxContours ); + + zone->first_point = 0; } return error; @@ -488,8 +477,7 @@ int j, k; - FT_MEM_SET( num_matched_ids, 0, - sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES ); + FT_ARRAY_ZERO( num_matched_ids, TRICK_SFNT_IDS_NUM_FACES ); has_cvt = FALSE; has_fpgm = FALSE; has_prep = FALSE; @@ -787,7 +775,7 @@ FT_UInt instance_index = (FT_UInt)face_index >> 16; - if ( FT_HAS_MULTIPLE_MASTERS( ttface ) ) + if ( instance_index && FT_HAS_MULTIPLE_MASTERS( ttface ) ) { error = FT_Set_Named_Instance( ttface, instance_index ); if ( error ) @@ -885,75 +873,40 @@ * size :: * A handle to the size object. * - * pedantic :: - * Set if bytecode execution should be pedantic. - * * @Return: * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - tt_size_run_fpgm( TT_Size size, - FT_Bool pedantic ) + tt_size_run_fpgm( TT_Size size ) { TT_Face face = (TT_Face)size->root.face; - TT_ExecContext exec; + TT_ExecContext exec = size->context; FT_Error error; - exec = size->context; - error = TT_Load_Context( exec, face, size ); if ( error ) return error; - exec->callTop = 0; - exec->top = 0; - - exec->period = 64; - exec->phase = 0; - exec->threshold = 0; - - exec->instruction_trap = FALSE; - exec->F_dot_P = 0x4000L; - - exec->pedantic_hinting = pedantic; - - { - FT_Size_Metrics* size_metrics = &exec->metrics; - TT_Size_Metrics* tt_metrics = &exec->tt_metrics; - - - size_metrics->x_ppem = 0; - size_metrics->y_ppem = 0; - size_metrics->x_scale = 0; - size_metrics->y_scale = 0; - - tt_metrics->ppem = 0; - tt_metrics->scale = 0; - tt_metrics->ratio = 0x10000L; - } - - /* allow font program execution */ - TT_Set_CodeRange( exec, - tt_coderange_font, - face->font_program, - (FT_Long)face->font_program_size ); - /* disable CVT and glyph programs coderange */ TT_Clear_CodeRange( exec, tt_coderange_cvt ); TT_Clear_CodeRange( exec, tt_coderange_glyph ); if ( face->font_program_size > 0 ) { - TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); + /* allow font program execution */ + TT_Set_CodeRange( exec, + tt_coderange_font, + face->font_program, + (FT_Long)face->font_program_size ); + + exec->pts.n_points = 0; + exec->pts.n_contours = 0; FT_TRACE4(( "Executing `fpgm' table.\n" )); - error = face->interpreter( exec ); -#ifdef FT_DEBUG_LEVEL_TRACE - if ( error ) - FT_TRACE4(( " interpretation failed with error code 0x%x\n", - error )); -#endif + error = TT_Run_Context( exec, size ); + FT_TRACE4(( error ? " failed (error code 0x%x)\n" : "", + error )); } else error = FT_Err_Ok; @@ -979,212 +932,146 @@ * size :: * A handle to the size object. * - * pedantic :: - * Set if bytecode execution should be pedantic. - * * @Return: * FreeType error code. 0 means success. */ FT_LOCAL_DEF( FT_Error ) - tt_size_run_prep( TT_Size size, - FT_Bool pedantic ) + tt_size_run_prep( TT_Size size ) { TT_Face face = (TT_Face)size->root.face; - TT_ExecContext exec; + TT_ExecContext exec = size->context; FT_Error error; FT_UInt i; - /* Scale the cvt values to the new ppem. */ - /* By default, we use the y ppem value for scaling. */ - FT_TRACE6(( "CVT values:\n" )); - for ( i = 0; i < size->cvt_size; i++ ) - { - /* Unscaled CVT values are already stored in 26.6 format. */ - /* Note that this scaling operation is very sensitive to rounding; */ - /* the integer division by 64 must be applied to the first argument. */ - size->cvt[i] = FT_MulFix( face->cvt[i] / 64, size->ttmetrics.scale ); - FT_TRACE6(( " %3d: %f (%f)\n", - i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 )); - } - FT_TRACE6(( "\n" )); + /* set default GS, twilight points, and storage */ + /* before CV program can modify them. */ + size->GS = tt_default_graphics_state; - exec = size->context; + /* all twilight points are originally zero */ + FT_ARRAY_ZERO( size->twilight.org, size->twilight.n_points ); + FT_ARRAY_ZERO( size->twilight.cur, size->twilight.n_points ); error = TT_Load_Context( exec, face, size ); if ( error ) return error; - exec->callTop = 0; - exec->top = 0; + /* clear storage area */ + FT_ARRAY_ZERO( exec->storage, exec->storeSize ); - exec->instruction_trap = FALSE; - - exec->pedantic_hinting = pedantic; - - TT_Set_CodeRange( exec, - tt_coderange_cvt, - face->cvt_program, - (FT_Long)face->cvt_program_size ); + /* Scale the cvt values to the new ppem. */ + /* By default, we use the y ppem value for scaling. */ + FT_TRACE6(( "CVT values:\n" )); + for ( i = 0; i < exec->cvtSize; i++ ) + { + /* Unscaled CVT values are already stored in 26.6 format. */ + /* Note that this scaling operation is very sensitive to rounding; */ + /* the integer division by 64 must be applied to the first argument. */ + exec->cvt[i] = FT_MulFix( face->cvt[i] / 64, size->ttmetrics.scale ); + FT_TRACE6(( " %3u: %f (%f)\n", + i, (double)face->cvt[i] / 64, (double)exec->cvt[i] / 64 )); + } + FT_TRACE6(( "\n" )); TT_Clear_CodeRange( exec, tt_coderange_glyph ); if ( face->cvt_program_size > 0 ) { - TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); + /* allow CV program execution */ + TT_Set_CodeRange( exec, + tt_coderange_cvt, + face->cvt_program, + (FT_Long)face->cvt_program_size ); + + exec->pts.n_points = 0; + exec->pts.n_contours = 0; FT_TRACE4(( "Executing `prep' table.\n" )); - error = face->interpreter( exec ); -#ifdef FT_DEBUG_LEVEL_TRACE - if ( error ) - FT_TRACE4(( " interpretation failed with error code 0x%x\n", - error )); -#endif + error = TT_Run_Context( exec, size ); + FT_TRACE4(( error ? " failed (error code 0x%x)\n" : "", + error )); } else error = FT_Err_Ok; size->cvt_ready = error; - /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ - /* graphics state variables to be modified by the CVT program. */ - - exec->GS.dualVector.x = 0x4000; - exec->GS.dualVector.y = 0; - exec->GS.projVector.x = 0x4000; - exec->GS.projVector.y = 0x0; - exec->GS.freeVector.x = 0x4000; - exec->GS.freeVector.y = 0x0; - - exec->GS.rp0 = 0; - exec->GS.rp1 = 0; - exec->GS.rp2 = 0; - - exec->GS.gep0 = 1; - exec->GS.gep1 = 1; - exec->GS.gep2 = 1; - - exec->GS.loop = 1; - - /* save as default graphics state */ - size->GS = exec->GS; - - TT_Save_Context( exec, size ); + if ( !error ) + TT_Save_Context( exec, size ); return error; } static void - tt_size_done_bytecode( FT_Size ftsize ) + tt_size_done_bytecode( TT_Size size ) { - TT_Size size = (TT_Size)ftsize; - TT_Face face = (TT_Face)ftsize->face; - FT_Memory memory = face->root.memory; + FT_Memory memory = size->root.face->memory; + TT_ExecContext exec = size->context; - if ( size->context ) + + if ( exec ) { - TT_Done_Context( size->context ); + FT_FREE( exec->stack ); + FT_FREE( exec->FDefs ); + + TT_Done_Context( exec ); size->context = NULL; } - FT_FREE( size->cvt ); - size->cvt_size = 0; - - /* free storage area */ - FT_FREE( size->storage ); - size->storage_size = 0; - /* twilight zone */ - tt_glyphzone_done( &size->twilight ); - - FT_FREE( size->function_defs ); - FT_FREE( size->instruction_defs ); - - size->num_function_defs = 0; - size->max_function_defs = 0; - size->num_instruction_defs = 0; - size->max_instruction_defs = 0; - - size->max_func = 0; - size->max_ins = 0; - - size->bytecode_ready = -1; - size->cvt_ready = -1; + tt_glyphzone_done( memory, &size->twilight ); } /* Initialize bytecode-related fields in the size object. */ /* We do this only if bytecode interpretation is really needed. */ - static FT_Error - tt_size_init_bytecode( FT_Size ftsize, + FT_LOCAL_DEF( FT_Error ) + tt_size_init_bytecode( TT_Size size, FT_Bool pedantic ) { FT_Error error; - TT_Size size = (TT_Size)ftsize; - TT_Face face = (TT_Face)ftsize->face; - FT_Memory memory = face->root.memory; + TT_Face face = (TT_Face)size->root.face; + FT_Memory memory = size->root.face->memory; FT_UShort n_twilight; TT_MaxProfile* maxp = &face->max_profile; + TT_ExecContext exec; - /* clean up bytecode related data */ - FT_FREE( size->function_defs ); - FT_FREE( size->instruction_defs ); - FT_FREE( size->cvt ); - FT_FREE( size->storage ); + exec = TT_New_Context( (TT_Driver)face->root.driver ); + if ( !exec ) + return FT_THROW( Could_Not_Find_Context ); - if ( size->context ) - TT_Done_Context( size->context ); - tt_glyphzone_done( &size->twilight ); + exec->pedantic_hinting = pedantic; - size->bytecode_ready = -1; - size->cvt_ready = -1; + exec->maxFDefs = maxp->maxFunctionDefs; + exec->maxIDefs = maxp->maxInstructionDefs; - size->context = TT_New_Context( (TT_Driver)face->root.driver ); - - size->max_function_defs = maxp->maxFunctionDefs; - size->max_instruction_defs = maxp->maxInstructionDefs; - - size->num_function_defs = 0; - size->num_instruction_defs = 0; - - size->max_func = 0; - size->max_ins = 0; - - size->cvt_size = face->cvt_size; - size->storage_size = maxp->maxStorage; - - /* Set default metrics */ - { - TT_Size_Metrics* tt_metrics = &size->ttmetrics; - - - tt_metrics->rotated = FALSE; - tt_metrics->stretched = FALSE; - - /* Set default engine compensation. Value 3 is not described */ - /* in the OpenType specification (as of Mai 2019), but Greg */ - /* says that MS handles it the same as `gray'. */ - /* */ - /* The Apple specification says that the compensation for */ - /* `gray' is always zero. FreeType doesn't do any */ - /* compensation at all. */ - tt_metrics->compensations[0] = 0; /* gray */ - tt_metrics->compensations[1] = 0; /* black */ - tt_metrics->compensations[2] = 0; /* white */ - tt_metrics->compensations[3] = 0; /* zero */ - } - - /* allocate function defs, instruction defs, cvt, and storage area */ - if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || - FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || - FT_NEW_ARRAY( size->cvt, size->cvt_size ) || - FT_NEW_ARRAY( size->storage, size->storage_size ) ) + if ( FT_NEW_ARRAY( exec->FDefs, exec->maxFDefs + exec->maxIDefs ) ) goto Exit; - /* reserve twilight zone */ + exec->IDefs = exec->FDefs + exec->maxFDefs; + + exec->numFDefs = 0; + exec->numIDefs = 0; + + exec->maxFunc = 0; + exec->maxIns = 0; + + /* XXX: We reserve a little more elements on the stack to deal */ + /* with broken fonts like arialbs, courbs, timesbs, etc. */ + exec->stackSize = maxp->maxStackElements + 32; + exec->storeSize = maxp->maxStorage; + exec->cvtSize = face->cvt_size; + + if ( FT_NEW_ARRAY( exec->stack, + exec->stackSize + + (FT_Long)( exec->storeSize + exec->cvtSize ) ) ) + goto Exit; + + /* reserve twilight zone and set GS before fpgm is executed, */ + /* just in case, even though fpgm should not touch them */ n_twilight = maxp->maxTwilightPoints; /* there are 4 phantom points (do we need this?) */ @@ -1194,20 +1081,12 @@ if ( error ) goto Exit; - size->twilight.n_points = n_twilight; + size->GS = tt_default_graphics_state; + size->cvt_ready = -1; + size->context = exec; - size->GS = tt_default_graphics_state; - - /* set `face->interpreter' according to the debug hook present */ - { - FT_Library library = face->root.driver->root.library; - - - face->interpreter = (TT_Interpreter) - library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; - if ( !face->interpreter ) - face->interpreter = (TT_Interpreter)TT_RunIns; - } + size->ttmetrics.rotated = FALSE; + size->ttmetrics.stretched = FALSE; /* Fine, now run the font program! */ @@ -1217,62 +1096,16 @@ /* to be executed just once; calling it again is completely useless */ /* and might even lead to extremely slow behaviour if it is malformed */ /* (containing an infinite loop, for example). */ - error = tt_size_run_fpgm( size, pedantic ); + error = tt_size_run_fpgm( size ); return error; Exit: if ( error ) - tt_size_done_bytecode( ftsize ); + tt_size_done_bytecode( size ); return error; } - - FT_LOCAL_DEF( FT_Error ) - tt_size_ready_bytecode( TT_Size size, - FT_Bool pedantic ) - { - FT_Error error = FT_Err_Ok; - - - if ( size->bytecode_ready < 0 ) - error = tt_size_init_bytecode( (FT_Size)size, pedantic ); - else - error = size->bytecode_ready; - - if ( error ) - goto Exit; - - /* rescale CVT when needed */ - if ( size->cvt_ready < 0 ) - { - FT_UShort i; - - - /* all twilight points are originally zero */ - for ( i = 0; i < size->twilight.n_points; i++ ) - { - size->twilight.org[i].x = 0; - size->twilight.org[i].y = 0; - size->twilight.cur[i].x = 0; - size->twilight.cur[i].y = 0; - } - - /* clear storage area */ - for ( i = 0; i < size->storage_size; i++ ) - size->storage[i] = 0; - - size->GS = tt_default_graphics_state; - - error = tt_size_run_prep( size, pedantic ); - } - else - error = size->cvt_ready; - - Exit: - return error; - } - #endif /* TT_USE_BYTECODE_INTERPRETER */ @@ -1300,11 +1133,9 @@ #ifdef TT_USE_BYTECODE_INTERPRETER size->bytecode_ready = -1; - size->cvt_ready = -1; #endif - size->ttmetrics.valid = FALSE; - size->strike_index = 0xFFFFFFFFUL; + size->strike_index = 0xFFFFFFFFUL; return error; } @@ -1325,14 +1156,11 @@ FT_LOCAL_DEF( void ) tt_size_done( FT_Size ttsize ) /* TT_Size */ { - TT_Size size = (TT_Size)ttsize; - - #ifdef TT_USE_BYTECODE_INTERPRETER - tt_size_done_bytecode( ttsize ); + tt_size_done_bytecode( (TT_Size)ttsize ); +#else + FT_UNUSED( ttsize ); #endif - - size->ttmetrics.valid = FALSE; } @@ -1353,21 +1181,13 @@ * function must take `FT_Size` as a result. The passed `FT_Size` is * expected to point to a `TT_Size`. */ - FT_LOCAL_DEF( FT_Error ) + FT_LOCAL_DEF( void ) tt_size_reset_height( FT_Size ft_size ) { TT_Size size = (TT_Size)ft_size; - TT_Face face = (TT_Face)size->root.face; + TT_Face face = (TT_Face)ft_size->face; FT_Size_Metrics* size_metrics = &size->hinted_metrics; - size->ttmetrics.valid = FALSE; - - /* copy the result from base layer */ - *size_metrics = size->root.metrics; - - if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 ) - return FT_THROW( Invalid_PPem ); - /* This bit flag, if set, indicates that the ppems must be */ /* rounded to integers. Nearly all TrueType fonts have this bit */ /* set, as hinting won't work really well otherwise. */ @@ -1385,10 +1205,6 @@ FT_MulFix( face->root.height, size_metrics->y_scale ) ); } - - size->ttmetrics.valid = TRUE; - - return FT_Err_Ok; } @@ -1408,14 +1224,20 @@ FT_LOCAL_DEF( FT_Error ) tt_size_reset( TT_Size size ) { - FT_Error error; TT_Face face = (TT_Face)size->root.face; FT_Size_Metrics* size_metrics = &size->hinted_metrics; - error = tt_size_reset_height( (FT_Size)size ); - if ( error ) - return error; + /* invalidate the size object first */ + size->ttmetrics.ppem = 0; + + if ( size->root.metrics.x_ppem == 0 || size->root.metrics.y_ppem == 0 ) + return FT_THROW( Invalid_PPem ); + + /* copy the result from base layer */ + *size_metrics = size->root.metrics; + + tt_size_reset_height( (FT_Size)size ); if ( face->header.Flags & 8 ) { diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h index 9c36ca78362..28d6c7d855f 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h @@ -4,7 +4,7 @@ * * Objects manager (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -53,6 +53,8 @@ FT_BEGIN_HEADER typedef FT_GlyphSlot TT_GlyphSlot; +#ifdef TT_USE_BYTECODE_INTERPRETER + /************************************************************************** * * @Struct: @@ -67,21 +69,27 @@ FT_BEGIN_HEADER FT_UShort rp1; FT_UShort rp2; + FT_UShort gep0; + FT_UShort gep1; + FT_UShort gep2; + FT_UnitVector dualVector; FT_UnitVector projVector; FT_UnitVector freeVector; FT_Long loop; - FT_F26Dot6 minimum_distance; FT_Int round_state; + FT_F26Dot6 compensation[4]; /* device-specific compensations */ - FT_Bool auto_flip; + /* default values below can be modified by 'fpgm' and 'prep' */ + FT_F26Dot6 minimum_distance; FT_F26Dot6 control_value_cutin; FT_F26Dot6 single_width_cutin; FT_F26Dot6 single_width_value; FT_UShort delta_base; FT_UShort delta_shift; + FT_Bool auto_flip; FT_Byte instruct_control; /* According to Greg Hitchcock from Microsoft, the `scan_control' */ /* variable as documented in the TrueType specification is a 32-bit */ @@ -90,17 +98,12 @@ FT_BEGIN_HEADER FT_Bool scan_control; FT_Int scan_type; - FT_UShort gep0; - FT_UShort gep1; - FT_UShort gep2; - } TT_GraphicsState; -#ifdef TT_USE_BYTECODE_INTERPRETER - FT_LOCAL( void ) - tt_glyphzone_done( TT_GlyphZone zone ); + tt_glyphzone_done( FT_Memory memory, + TT_GlyphZone zone ); FT_LOCAL( FT_Error ) tt_glyphzone_new( FT_Memory memory, @@ -112,73 +115,6 @@ FT_BEGIN_HEADER - /************************************************************************** - * - * EXECUTION SUBTABLES - * - * These sub-tables relate to instruction execution. - * - */ - - -#define TT_MAX_CODE_RANGES 3 - - - /************************************************************************** - * - * There can only be 3 active code ranges at once: - * - the Font Program - * - the CVT Program - * - a glyph's instructions set - */ - typedef enum TT_CodeRange_Tag_ - { - tt_coderange_none = 0, - tt_coderange_font, - tt_coderange_cvt, - tt_coderange_glyph - - } TT_CodeRange_Tag; - - - typedef struct TT_CodeRange_ - { - FT_Byte* base; - FT_Long size; - - } TT_CodeRange; - - typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES]; - - - /************************************************************************** - * - * Defines a function/instruction definition record. - */ - typedef struct TT_DefRecord_ - { - FT_Int range; /* in which code range is it located? */ - FT_Long start; /* where does it start? */ - FT_Long end; /* where does it end? */ - FT_UInt opc; /* function #, or instruction code */ - FT_Bool active; /* is it active? */ - - } TT_DefRecord, *TT_DefArray; - - - /************************************************************************** - * - * Subglyph transformation record. - */ - typedef struct TT_Transform_ - { - FT_Fixed xx, xy; /* transformation matrix coefficients */ - FT_Fixed yx, yy; - FT_F26Dot6 ox, oy; /* offsets */ - - } TT_Transform; - - /************************************************************************** * * A note regarding non-squared pixels: @@ -251,13 +187,9 @@ FT_BEGIN_HEADER FT_Long x_ratio; FT_Long y_ratio; - FT_UShort ppem; /* maximum ppem size */ FT_Long ratio; /* current ratio */ FT_Fixed scale; - - FT_F26Dot6 compensations[4]; /* device-specific compensations */ - - FT_Bool valid; + FT_UShort ppem; /* maximum ppem size */ FT_Bool rotated; /* `is the glyph rotated?'-flag */ FT_Bool stretched; /* `is the glyph stretched?'-flag */ @@ -288,27 +220,8 @@ FT_BEGIN_HEADER FT_Long point_size; /* for the `MPS' bytecode instruction */ - FT_UInt num_function_defs; /* number of function definitions */ - FT_UInt max_function_defs; - TT_DefArray function_defs; /* table of function definitions */ - - FT_UInt num_instruction_defs; /* number of ins. definitions */ - FT_UInt max_instruction_defs; - TT_DefArray instruction_defs; /* table of ins. definitions */ - - FT_UInt max_func; - FT_UInt max_ins; - - TT_CodeRangeTable codeRangeTable; - TT_GraphicsState GS; - FT_ULong cvt_size; /* the scaled control value table */ - FT_Long* cvt; - - FT_UShort storage_size; /* The storage area is now part of */ - FT_Long* storage; /* the instance */ - TT_GlyphZoneRec twilight; /* The instance's twilight zone */ TT_ExecContext context; @@ -375,20 +288,18 @@ FT_BEGIN_HEADER #ifdef TT_USE_BYTECODE_INTERPRETER FT_LOCAL( FT_Error ) - tt_size_run_fpgm( TT_Size size, - FT_Bool pedantic ); + tt_size_run_fpgm( TT_Size size ); FT_LOCAL( FT_Error ) - tt_size_run_prep( TT_Size size, - FT_Bool pedantic ); + tt_size_run_prep( TT_Size size ); FT_LOCAL( FT_Error ) - tt_size_ready_bytecode( TT_Size size, - FT_Bool pedantic ); + tt_size_init_bytecode( TT_Size size, + FT_Bool pedantic ); #endif /* TT_USE_BYTECODE_INTERPRETER */ - FT_LOCAL( FT_Error ) + FT_LOCAL( void ) tt_size_reset_height( FT_Size size ); FT_LOCAL( FT_Error ) diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c index 9505b5f179f..827454d8574 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -110,7 +110,7 @@ if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 ) { - FT_TRACE2(( "glyph count mismatch! loca: %ld, maxp: %ld\n", + FT_TRACE2(( "glyph count mismatch! loca: %lu, maxp: %ld\n", face->num_locations - 1, face->root.num_glyphs )); /* we only handle the case where `maxp' gives a larger value */ @@ -151,7 +151,7 @@ face->num_locations = (FT_ULong)face->root.num_glyphs + 1; table_len = new_loca_len; - FT_TRACE2(( "adjusting num_locations to %ld\n", + FT_TRACE2(( "adjusting num_locations to %lu\n", face->num_locations )); } else @@ -225,7 +225,7 @@ if ( pos1 > ttface->glyf_len ) { FT_TRACE1(( "tt_face_get_location:" - " too large offset (0x%08lx) found for glyph index %d,\n", + " too large offset (0x%08lx) found for glyph index %u,\n", pos1, gindex )); FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", @@ -240,17 +240,17 @@ if ( gindex == ttface->num_locations - 2 ) { FT_TRACE1(( "tt_face_get_location:" - " too large size (%ld bytes) found for glyph index %d,\n", + " too large size (%lu bytes) found for glyph index %u,\n", pos2 - pos1, gindex )); FT_TRACE1(( " " - " truncating at the end of `glyf' table to %ld bytes\n", + " truncating at the end of `glyf' table to %lu bytes\n", ttface->glyf_len - pos1 )); pos2 = ttface->glyf_len; } else { FT_TRACE1(( "tt_face_get_location:" - " too large offset (0x%08lx) found for glyph index %d,\n", + " too large offset (0x%08lx) found for glyph index %u,\n", pos2, gindex + 1 )); FT_TRACE1(( " " " exceeding the end of `glyf' table (0x%08lx)\n", @@ -419,7 +419,7 @@ if ( FT_FRAME_EXTRACT( table_len, face->font_program ) ) goto Exit; - FT_TRACE2(( "loaded, %12ld bytes\n", face->font_program_size )); + FT_TRACE2(( "loaded, %12lu bytes\n", face->font_program_size )); } Exit: @@ -482,7 +482,7 @@ if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) ) goto Exit; - FT_TRACE2(( "loaded, %12ld bytes\n", face->cvt_program_size )); + FT_TRACE2(( "loaded, %12lu bytes\n", face->cvt_program_size )); } Exit: diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h index bc32b58020c..bb4d3c9cc55 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h @@ -4,7 +4,7 @@ * * TrueType-specific tables loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c deleted file mode 100644 index d811beef0df..00000000000 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.c +++ /dev/null @@ -1,1013 +0,0 @@ -/**************************************************************************** - * - * ttsubpix.c - * - * TrueType Subpixel Hinting. - * - * Copyright (C) 2010-2023 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "ttsubpix.h" - - -#if defined( TT_USE_BYTECODE_INTERPRETER ) && \ - defined( TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY ) - - /************************************************************************** - * - * These rules affect how the TT Interpreter does hinting, with the - * goal of doing subpixel hinting by (in general) ignoring x moves. - * Some of these rules are fixes that go above and beyond the - * stated techniques in the MS whitepaper on Cleartype, due to - * artifacts in many glyphs. So, these rules make some glyphs render - * better than they do in the MS rasterizer. - * - * "" string or 0 int/char indicates to apply to all glyphs. - * "-" used as dummy placeholders, but any non-matching string works. - * - * Some of this could arguably be implemented in fontconfig, however: - * - * - Fontconfig can't set things on a glyph-by-glyph basis. - * - The tweaks that happen here are very low-level, from an average - * user's point of view and are best implemented in the hinter. - * - * The goal is to make the subpixel hinting techniques as generalized - * as possible across all fonts to prevent the need for extra rules such - * as these. - * - * The rule structure is designed so that entirely new rules can easily - * be added when a new compatibility feature is discovered. - * - * The rule structures could also use some enhancement to handle ranges. - * - * ****************** WORK IN PROGRESS ******************* - */ - - /* These are `classes' of fonts that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define FAMILY_CLASS_RULES_SIZE 7 - - static const SPH_Font_Class FAMILY_CLASS_Rules - [FAMILY_CLASS_RULES_SIZE] = - { - { "MS Legacy Fonts", - { "Aharoni", - "Andale Mono", - "Andalus", - "Angsana New", - "AngsanaUPC", - "Arabic Transparent", - "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Batang", - "Browallia New", - "BrowalliaUPC", - "Comic Sans MS", - "Cordia New", - "CordiaUPC", - "Courier New", - "DFKai-SB", - "David Transparent", - "David", - "DilleniaUPC", - "Estrangelo Edessa", - "EucrosiaUPC", - "FangSong_GB2312", - "Fixed Miriam Transparent", - "FrankRuehl", - "Franklin Gothic Medium", - "FreesiaUPC", - "Garamond", - "Gautami", - "Georgia", - "Gulim", - "Impact", - "IrisUPC", - "JasmineUPC", - "KaiTi_GB2312", - "KodchiangUPC", - "Latha", - "Levenim MT", - "LilyUPC", - "Lucida Console", - "Lucida Sans Unicode", - "MS Gothic", - "MS Mincho", - "MV Boli", - "Mangal", - "Marlett", - "Microsoft Sans Serif", - "Mingliu", - "Miriam Fixed", - "Miriam Transparent", - "Miriam", - "Narkisim", - "Palatino Linotype", - "Raavi", - "Rod Transparent", - "Rod", - "Shruti", - "SimHei", - "Simplified Arabic Fixed", - "Simplified Arabic", - "Simsun", - "Sylfaen", - "Symbol", - "Tahoma", - "Times New Roman", - "Traditional Arabic", - "Trebuchet MS", - "Tunga", - "Verdana", - "Webdings", - "Wingdings", - "", - }, - }, - { "Core MS Legacy Fonts", - { "Arial Black", - "Arial Narrow", - "Arial Unicode MS", - "Arial", - "Comic Sans MS", - "Courier New", - "Garamond", - "Georgia", - "Impact", - "Lucida Console", - "Lucida Sans Unicode", - "Microsoft Sans Serif", - "Palatino Linotype", - "Tahoma", - "Times New Roman", - "Trebuchet MS", - "Verdana", - "", - }, - }, - { "Apple Legacy Fonts", - { "Geneva", - "Times", - "Monaco", - "Century", - "Chalkboard", - "Lobster", - "Century Gothic", - "Optima", - "Lucida Grande", - "Gill Sans", - "Baskerville", - "Helvetica", - "Helvetica Neue", - "", - }, - }, - { "Legacy Sans Fonts", - { "Andale Mono", - "Arial Unicode MS", - "Arial", - "Century Gothic", - "Comic Sans MS", - "Franklin Gothic Medium", - "Geneva", - "Lucida Console", - "Lucida Grande", - "Lucida Sans Unicode", - "Lucida Sans Typewriter", - "Microsoft Sans Serif", - "Monaco", - "Tahoma", - "Trebuchet MS", - "Verdana", - "", - }, - }, - - { "Misc Legacy Fonts", - { "Dark Courier", "", }, }, - { "Verdana Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", "", }, }, - { "Verdana and Clones", - { "DejaVu Sans", - "Bitstream Vera Sans", - "Verdana", "", }, }, - }; - - - /* Define this to force natural (i.e. not bitmap-compatible) widths. */ - /* The default leans strongly towards natural widths except for a few */ - /* legacy fonts where a selective combination produces nicer results. */ -/* #define FORCE_NATURAL_WIDTHS */ - - - /* Define `classes' of styles that can be grouped together and used in */ - /* rules below. A blank entry "" is required at the end of these! */ -#define STYLE_CLASS_RULES_SIZE 5 - - static const SPH_Font_Class STYLE_CLASS_Rules - [STYLE_CLASS_RULES_SIZE] = - { - { "Regular Class", - { "Regular", - "Book", - "Medium", - "Roman", - "Normal", - "", - }, - }, - { "Regular/Italic Class", - { "Regular", - "Book", - "Medium", - "Italic", - "Oblique", - "Roman", - "Normal", - "", - }, - }, - { "Bold/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "", - }, - }, - { "Bold/Italic/BoldItalic Class", - { "Bold", - "Bold Italic", - "Black", - "Italic", - "Oblique", - "", - }, - }, - { "Regular/Bold Class", - { "Regular", - "Book", - "Medium", - "Normal", - "Roman", - "Bold", - "Black", - "", - }, - }, - }; - - - /* Force special legacy fixes for fonts. */ -#define COMPATIBILITY_MODE_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBILITY_MODE_Rules - [COMPATIBILITY_MODE_RULES_SIZE] = - { - { "Verdana Clones", 0, "", 0 }, - }; - - - /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting. */ -#define PIXEL_HINTING_RULES_SIZE 2 - - static const SPH_TweakRule PIXEL_HINTING_Rules - [PIXEL_HINTING_RULES_SIZE] = - { - /* these characters are almost always safe */ - { "Courier New", 12, "Italic", 'z' }, - { "Courier New", 11, "Italic", 'z' }, - }; - - - /* Subpixel hinting ignores SHPIX rules on X. Force SHPIX for these. */ -#define DO_SHPIX_RULES_SIZE 1 - - static const SPH_TweakRule DO_SHPIX_Rules - [DO_SHPIX_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE 4 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules - [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* fix vwxyz thinness */ - { "Consolas", 0, "", 0 }, - /* Fix thin middle stems */ - { "Core MS Legacy Fonts", 0, "Regular", 0 }, - /* Cyrillic small letter I */ - { "Legacy Sans Fonts", 0, "", 0 }, - /* Fix artifacts with some Regular & Bold */ - { "Verdana Clones", 0, "", 0 }, - }; - - -#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - /* Fixes < and > */ - { "Courier New", 0, "Regular", 0 }, - }; - - - /* Skip Y moves that start with a point that is not on a Y pixel */ - /* boundary and don't move that point to a Y pixel boundary. */ -#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE 2 - - static const SPH_TweakRule SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules - [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] = - { - /* Maintain thickness of diagonal in 'N' */ - { "Times New Roman", 0, "Regular/Bold Class", 'N' }, - { "Georgia", 0, "Regular/Bold Class", 'N' }, - }; - - - /* Skip Y moves that move a point off a Y pixel boundary. */ -#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules - [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions - [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Round moves that don't move a point to a Y pixel boundary. */ -#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE 2 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules - [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] = - { - /* Droid font instructions don't snap Y to pixels */ - { "Droid Sans", 0, "Regular/Italic Class", 0 }, - { "Droid Sans Mono", 0, "", 0 }, - }; - - -#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE 1 - - static const SPH_TweakRule ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions - [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Allow a Direct_Move along X freedom vector if matched. */ -#define ALLOW_X_DMOVE_RULES_SIZE 1 - - static const SPH_TweakRule ALLOW_X_DMOVE_Rules - [ALLOW_X_DMOVE_RULES_SIZE] = - { - /* Fixes vanishing diagonal in 4 */ - { "Verdana", 0, "Regular", '4' }, - }; - - - /* Return MS rasterizer version 35 if matched. */ -#define RASTERIZER_35_RULES_SIZE 8 - - static const SPH_TweakRule RASTERIZER_35_Rules - [RASTERIZER_35_RULES_SIZE] = - { - /* This seems to be the only way to make these look good */ - { "Times New Roman", 0, "Regular", 'i' }, - { "Times New Roman", 0, "Regular", 'j' }, - { "Times New Roman", 0, "Regular", 'm' }, - { "Times New Roman", 0, "Regular", 'r' }, - { "Times New Roman", 0, "Regular", 'a' }, - { "Times New Roman", 0, "Regular", 'n' }, - { "Times New Roman", 0, "Regular", 'p' }, - { "Times", 0, "", 0 }, - }; - - - /* Don't round to the subpixel grid. Round to pixel grid. */ -#define NORMAL_ROUND_RULES_SIZE 1 - - static const SPH_TweakRule NORMAL_ROUND_Rules - [NORMAL_ROUND_RULES_SIZE] = - { - /* Fix serif thickness for certain ppems */ - /* Can probably be generalized somehow */ - { "Courier New", 0, "", 0 }, - }; - - - /* Skip IUP instructions if matched. */ -#define SKIP_IUP_RULES_SIZE 1 - - static const SPH_TweakRule SKIP_IUP_Rules - [SKIP_IUP_RULES_SIZE] = - { - { "Arial", 13, "Regular", 'a' }, - }; - - - /* Skip MIAP Twilight hack if matched. */ -#define MIAP_HACK_RULES_SIZE 1 - - static const SPH_TweakRule MIAP_HACK_Rules - [MIAP_HACK_RULES_SIZE] = - { - { "Geneva", 12, "", 0 }, - }; - - - /* Skip DELTAP instructions if matched. */ -#define ALWAYS_SKIP_DELTAP_RULES_SIZE 23 - - static const SPH_TweakRule ALWAYS_SKIP_DELTAP_Rules - [ALWAYS_SKIP_DELTAP_RULES_SIZE] = - { - { "Georgia", 0, "Regular", 'k' }, - /* fix various problems with e in different versions */ - { "Trebuchet MS", 14, "Regular", 'e' }, - { "Trebuchet MS", 13, "Regular", 'e' }, - { "Trebuchet MS", 15, "Regular", 'e' }, - { "Trebuchet MS", 0, "Italic", 'v' }, - { "Trebuchet MS", 0, "Italic", 'w' }, - { "Trebuchet MS", 0, "Regular", 'Y' }, - { "Arial", 11, "Regular", 's' }, - /* prevent problems with '3' and others */ - { "Verdana", 10, "Regular", 0 }, - { "Verdana", 9, "Regular", 0 }, - /* Cyrillic small letter short I */ - { "Legacy Sans Fonts", 0, "", 0x438 }, - { "Legacy Sans Fonts", 0, "", 0x439 }, - { "Arial", 10, "Regular", '6' }, - { "Arial", 0, "Bold/BoldItalic Class", 'a' }, - /* Make horizontal stems consistent with the rest */ - { "Arial", 24, "Bold", 'a' }, - { "Arial", 25, "Bold", 'a' }, - { "Arial", 24, "Bold", 's' }, - { "Arial", 25, "Bold", 's' }, - { "Arial", 34, "Bold", 's' }, - { "Arial", 35, "Bold", 's' }, - { "Arial", 36, "Bold", 's' }, - { "Arial", 25, "Regular", 's' }, - { "Arial", 26, "Regular", 's' }, - }; - - - /* Always do DELTAP instructions if matched. */ -#define ALWAYS_DO_DELTAP_RULES_SIZE 1 - - static const SPH_TweakRule ALWAYS_DO_DELTAP_Rules - [ALWAYS_DO_DELTAP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow ALIGNRP after IUP. */ -#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_ALIGNRP_AFTER_IUP_Rules - [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* Don't allow DELTAP after IUP. */ -#define NO_DELTAP_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_DELTAP_AFTER_IUP_Rules - [NO_DELTAP_AFTER_IUP_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - - /* Don't allow CALL after IUP. */ -#define NO_CALL_AFTER_IUP_RULES_SIZE 1 - - static const SPH_TweakRule NO_CALL_AFTER_IUP_Rules - [NO_CALL_AFTER_IUP_RULES_SIZE] = - { - /* Prevent creation of dents in outline */ - { "-", 0, "", 0 }, - }; - - - /* De-embolden these glyphs slightly. */ -#define DEEMBOLDEN_RULES_SIZE 9 - - static const SPH_TweakRule DEEMBOLDEN_Rules - [DEEMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Bold", 'A' }, - { "Courier New", 0, "Bold", 'W' }, - { "Courier New", 0, "Bold", 'w' }, - { "Courier New", 0, "Bold", 'M' }, - { "Courier New", 0, "Bold", 'X' }, - { "Courier New", 0, "Bold", 'K' }, - { "Courier New", 0, "Bold", 'x' }, - { "Courier New", 0, "Bold", 'z' }, - { "Courier New", 0, "Bold", 'v' }, - }; - - - /* Embolden these glyphs slightly. */ -#define EMBOLDEN_RULES_SIZE 2 - - static const SPH_TweakRule EMBOLDEN_Rules - [EMBOLDEN_RULES_SIZE] = - { - { "Courier New", 0, "Regular", 0 }, - { "Courier New", 0, "Italic", 0 }, - }; - - - /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7 */ - /* similar to Windows XP. */ -#define TIMES_NEW_ROMAN_HACK_RULES_SIZE 12 - - static const SPH_TweakRule TIMES_NEW_ROMAN_HACK_Rules - [TIMES_NEW_ROMAN_HACK_RULES_SIZE] = - { - { "Times New Roman", 16, "Italic", '2' }, - { "Times New Roman", 16, "Italic", '5' }, - { "Times New Roman", 16, "Italic", '7' }, - { "Times New Roman", 16, "Regular", '2' }, - { "Times New Roman", 16, "Regular", '5' }, - { "Times New Roman", 16, "Regular", '7' }, - { "Times New Roman", 17, "Italic", '2' }, - { "Times New Roman", 17, "Italic", '5' }, - { "Times New Roman", 17, "Italic", '7' }, - { "Times New Roman", 17, "Regular", '2' }, - { "Times New Roman", 17, "Regular", '5' }, - { "Times New Roman", 17, "Regular", '7' }, - }; - - - /* This fudges distance on 2 to get rid of the vanishing stem issue. */ - /* A real solution to this is certainly welcome. */ -#define COURIER_NEW_2_HACK_RULES_SIZE 15 - - static const SPH_TweakRule COURIER_NEW_2_HACK_Rules - [COURIER_NEW_2_HACK_RULES_SIZE] = - { - { "Courier New", 10, "Regular", '2' }, - { "Courier New", 11, "Regular", '2' }, - { "Courier New", 12, "Regular", '2' }, - { "Courier New", 13, "Regular", '2' }, - { "Courier New", 14, "Regular", '2' }, - { "Courier New", 15, "Regular", '2' }, - { "Courier New", 16, "Regular", '2' }, - { "Courier New", 17, "Regular", '2' }, - { "Courier New", 18, "Regular", '2' }, - { "Courier New", 19, "Regular", '2' }, - { "Courier New", 20, "Regular", '2' }, - { "Courier New", 21, "Regular", '2' }, - { "Courier New", 22, "Regular", '2' }, - { "Courier New", 23, "Regular", '2' }, - { "Courier New", 24, "Regular", '2' }, - }; - - -#ifndef FORCE_NATURAL_WIDTHS - - /* Use compatible widths with these glyphs. Compatible widths is always */ - /* on when doing B/W TrueType instructing, but is used selectively here, */ - /* typically on glyphs with 3 or more vertical stems. */ -#define COMPATIBLE_WIDTHS_RULES_SIZE 38 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "Arial Unicode MS", 12, "Regular Class", 'm' }, - { "Arial Unicode MS", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 10, "Regular Class", 0x448 }, - { "Arial", 11, "Regular Class", 'm' }, - { "Arial", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 12, "Regular Class", 0x448 }, - { "Arial", 13, "Regular Class", 0x448 }, - { "Arial", 14, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Arial", 14, "Regular Class", 0x448 }, - { "Arial", 15, "Regular Class", 0x448 }, - { "Arial", 17, "Regular Class", 'm' }, - { "DejaVu Sans", 15, "Regular Class", 0 }, - { "Microsoft Sans Serif", 11, "Regular Class", 0 }, - { "Microsoft Sans Serif", 12, "Regular Class", 0 }, - { "Segoe UI", 11, "Regular Class", 0 }, - { "Monaco", 0, "Regular Class", 0 }, - { "Segoe UI", 12, "Regular Class", 'm' }, - { "Segoe UI", 14, "Regular Class", 'm' }, - { "Tahoma", 11, "Regular Class", 0 }, - { "Times New Roman", 16, "Regular Class", 'c' }, - { "Times New Roman", 16, "Regular Class", 'm' }, - { "Times New Roman", 16, "Regular Class", 'o' }, - { "Times New Roman", 16, "Regular Class", 'w' }, - { "Trebuchet MS", 11, "Regular Class", 0 }, - { "Trebuchet MS", 12, "Regular Class", 0 }, - { "Trebuchet MS", 14, "Regular Class", 0 }, - { "Trebuchet MS", 15, "Regular Class", 0 }, - { "Ubuntu", 12, "Regular Class", 'm' }, - /* Cyrillic small letter sha */ - { "Verdana", 10, "Regular Class", 0x448 }, - { "Verdana", 11, "Regular Class", 0x448 }, - { "Verdana and Clones", 12, "Regular Class", 'i' }, - { "Verdana and Clones", 12, "Regular Class", 'j' }, - { "Verdana and Clones", 12, "Regular Class", 'l' }, - { "Verdana and Clones", 12, "Regular Class", 'm' }, - { "Verdana and Clones", 13, "Regular Class", 'i' }, - { "Verdana and Clones", 13, "Regular Class", 'j' }, - { "Verdana and Clones", 13, "Regular Class", 'l' }, - { "Verdana and Clones", 14, "Regular Class", 'm' }, - }; - - - /* Scaling slightly in the x-direction prior to hinting results in */ - /* more visually pleasing glyphs in certain cases. */ - /* This sometimes needs to be coordinated with compatible width rules. */ - /* A value of 1000 corresponds to a scaled value of 1.0. */ - -#define X_SCALING_RULES_SIZE 50 - - static const SPH_ScaleRule X_SCALING_Rules[X_SCALING_RULES_SIZE] = - { - { "DejaVu Sans", 12, "Regular Class", 'm', 950 }, - { "Verdana and Clones", 12, "Regular Class", 'a', 1100 }, - { "Verdana and Clones", 13, "Regular Class", 'a', 1050 }, - { "Arial", 11, "Regular Class", 'm', 975 }, - { "Arial", 12, "Regular Class", 'm', 1050 }, - /* Cyrillic small letter el */ - { "Arial", 13, "Regular Class", 0x43B, 950 }, - { "Arial", 13, "Regular Class", 'o', 950 }, - { "Arial", 13, "Regular Class", 'e', 950 }, - { "Arial", 14, "Regular Class", 'm', 950 }, - /* Cyrillic small letter el */ - { "Arial", 15, "Regular Class", 0x43B, 925 }, - { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 }, - { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 }, - { "DejaVu Sans", 12, "Regular Class", 'l', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'i', 975 }, - { "DejaVu Sans", 12, "Regular Class", 'j', 975 }, - { "DejaVu Sans", 13, "Regular Class", 'l', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'i', 950 }, - { "DejaVu Sans", 13, "Regular Class", 'j', 950 }, - { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 }, - { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 }, - { "Georgia", 10, "", 0, 1050 }, - { "Georgia", 11, "", 0, 1100 }, - { "Georgia", 12, "", 0, 1025 }, - { "Georgia", 13, "", 0, 1050 }, - { "Georgia", 16, "", 0, 1050 }, - { "Georgia", 17, "", 0, 1030 }, - { "Liberation Sans", 12, "Regular Class", 'm', 1100 }, - { "Lucida Grande", 11, "Regular Class", 'm', 1100 }, - { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 }, - { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 12, "Regular Class", 'H', 1050 }, - { "Segoe UI", 12, "Regular Class", 'm', 1050 }, - { "Segoe UI", 14, "Regular Class", 'm', 1050 }, - { "Tahoma", 11, "Regular Class", 'i', 975 }, - { "Tahoma", 11, "Regular Class", 'l', 975 }, - { "Tahoma", 11, "Regular Class", 'j', 900 }, - { "Tahoma", 11, "Regular Class", 'm', 918 }, - { "Verdana", 10, "Regular/Italic Class", 0, 1100 }, - { "Verdana", 12, "Regular Class", 'm', 975 }, - { "Verdana", 12, "Regular/Italic Class", 0, 1050 }, - { "Verdana", 13, "Regular/Italic Class", 'i', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'j', 950 }, - { "Verdana", 13, "Regular/Italic Class", 'l', 950 }, - { "Verdana", 16, "Regular Class", 0, 1050 }, - { "Verdana", 9, "Regular/Italic Class", 0, 1050 }, - { "Times New Roman", 16, "Regular Class", 'm', 918 }, - { "Trebuchet MS", 11, "Regular Class", 'm', 800 }, - { "Trebuchet MS", 12, "Regular Class", 'm', 800 }, - }; - -#else - -#define COMPATIBLE_WIDTHS_RULES_SIZE 1 - - static const SPH_TweakRule COMPATIBLE_WIDTHS_Rules - [COMPATIBLE_WIDTHS_RULES_SIZE] = - { - { "-", 0, "", 0 }, - }; - - -#define X_SCALING_RULES_SIZE 1 - - static const SPH_ScaleRule X_SCALING_Rules - [X_SCALING_RULES_SIZE] = - { - { "-", 0, "", 0, 1000 }, - }; - -#endif /* FORCE_NATURAL_WIDTHS */ - - - static FT_Bool - is_member_of_family_class( const FT_String* detected_font_name, - const FT_String* rule_font_name ) - { - FT_UInt i, j; - - - /* Does font name match rule family? */ - if ( ft_strcmp( detected_font_name, rule_font_name ) == 0 ) - return TRUE; - - /* Is font name a wildcard ""? */ - if ( ft_strcmp( rule_font_name, "" ) == 0 ) - return TRUE; - - /* Is font name contained in a class list? */ - for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ ) - { - if ( ft_strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], - detected_font_name ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - static FT_Bool - is_member_of_style_class( const FT_String* detected_font_style, - const FT_String* rule_font_style ) - { - FT_UInt i, j; - - - /* Does font style match rule style? */ - if ( ft_strcmp( detected_font_style, rule_font_style ) == 0 ) - return TRUE; - - /* Is font style a wildcard ""? */ - if ( ft_strcmp( rule_font_style, "" ) == 0 ) - return TRUE; - - /* Is font style contained in a class list? */ - for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ ) - { - if ( ft_strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) - { - for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) - { - if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 ) - continue; - if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], - detected_font_style ) == 0 ) - return TRUE; - } - } - } - - return FALSE; - } - - - FT_LOCAL_DEF( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class ( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return TRUE; - } - - return FALSE; - } - - - static FT_UInt - scale_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_ScaleRule* rule, - FT_UInt num_rules ) - { - FT_UInt i; - - - /* rule checks may be able to be optimized further */ - for ( i = 0; i < num_rules; i++ ) - { - if ( family && - ( is_member_of_family_class ( family, rule[i].family ) ) ) - if ( rule[i].ppem == 0 || - rule[i].ppem == ppem ) - if ( style && - is_member_of_style_class( style, rule[i].style ) ) - if ( rule[i].glyph == 0 || - FT_Get_Char_Index( (FT_Face)face, - rule[i].glyph ) == glyph_index ) - return rule[i].scale; - } - - return 1000; - } - - - FT_LOCAL_DEF( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ) - { - return scale_test_tweak( face, family, ppem, style, glyph_index, - X_SCALING_Rules, X_SCALING_RULES_SIZE ); - } - - -#define TWEAK_RULES( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules, x##_RULES_SIZE ) ) \ - loader->exec->sph_tweak_flags |= SPH_TWEAK_##x - -#define TWEAK_RULES_EXCEPTIONS( x ) \ - if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ - x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \ - loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x - - - FT_LOCAL_DEF( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ) - { - TT_Face face = loader->face; - FT_String* family = face->root.family_name; - FT_UInt ppem = loader->size->metrics->x_ppem; - FT_String* style = face->root.style_name; - - - /* don't apply rules if style isn't set */ - if ( !face->root.style_name ) - return; - -#ifdef SPH_DEBUG_MORE_VERBOSE - printf( "%s,%d,%s,%c=%d ", - family, ppem, style, glyph_index, glyph_index ); -#endif - - TWEAK_RULES( PIXEL_HINTING ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING ) - { - loader->exec->ignore_x_mode = FALSE; - return; - } - - TWEAK_RULES( ALLOW_X_DMOVE ); - TWEAK_RULES( ALWAYS_DO_DELTAP ); - TWEAK_RULES( ALWAYS_SKIP_DELTAP ); - TWEAK_RULES( DEEMBOLDEN ); - TWEAK_RULES( DO_SHPIX ); - TWEAK_RULES( EMBOLDEN ); - TWEAK_RULES( MIAP_HACK ); - TWEAK_RULES( NORMAL_ROUND ); - TWEAK_RULES( NO_ALIGNRP_AFTER_IUP ); - TWEAK_RULES( NO_CALL_AFTER_IUP ); - TWEAK_RULES( NO_DELTAP_AFTER_IUP ); - TWEAK_RULES( RASTERIZER_35 ); - TWEAK_RULES( SKIP_IUP ); - - TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP ); - - TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES ); - - TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES ); - TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES ); - - if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) - { - if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 ) - { - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; - } - else - { - if ( loader->exec->rasterizer_version != - SPH_OPTION_SET_RASTERIZER_VERSION ) - { - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - loader->exec->size->cvt_ready = -1; - - tt_size_ready_bytecode( - loader->exec->size, - FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); - } - else - loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; - } - - if ( IS_HINTED( loader->load_flags ) ) - { - TWEAK_RULES( TIMES_NEW_ROMAN_HACK ); - TWEAK_RULES( COURIER_NEW_2_HACK ); - } - - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) ) - loader->exec->face->sph_compatibility_mode = TRUE; - - - if ( IS_HINTED( loader->load_flags ) ) - { - if ( sph_test_tweak( face, family, ppem, style, glyph_index, - COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) ) - loader->exec->compatible_widths |= TRUE; - } - } - -#else /* !(TT_USE_BYTECODE_INTERPRETER && */ - /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ - - /* ANSI C doesn't like empty source files */ - typedef int _tt_subpix_dummy; - -#endif /* !(TT_USE_BYTECODE_INTERPRETER && */ - /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ - - -/* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h deleted file mode 100644 index 62af4c272d1..00000000000 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttsubpix.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - * - * ttsubpix.h - * - * TrueType Subpixel Hinting. - * - * Copyright (C) 2010-2023 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used, - * modified, and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - */ - - -#ifndef TTSUBPIX_H_ -#define TTSUBPIX_H_ - -#include "ttobjs.h" -#include "ttinterp.h" - - -FT_BEGIN_HEADER - - -#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY - - /************************************************************************** - * - * ID flags to identify special functions at FDEF and runtime. - * - */ -#define SPH_FDEF_INLINE_DELTA_1 0x0000001 -#define SPH_FDEF_INLINE_DELTA_2 0x0000002 -#define SPH_FDEF_DIAGONAL_STROKE 0x0000004 -#define SPH_FDEF_VACUFORM_ROUND_1 0x0000008 -#define SPH_FDEF_TTFAUTOHINT_1 0x0000010 -#define SPH_FDEF_SPACING_1 0x0000020 -#define SPH_FDEF_SPACING_2 0x0000040 -#define SPH_FDEF_TYPEMAN_STROKES 0x0000080 -#define SPH_FDEF_TYPEMAN_DIAGENDCTRL 0x0000100 - - - /************************************************************************** - * - * Tweak flags that are set for each glyph by the below rules. - * - */ -#define SPH_TWEAK_ALLOW_X_DMOVE 0x0000001UL -#define SPH_TWEAK_ALWAYS_DO_DELTAP 0x0000002UL -#define SPH_TWEAK_ALWAYS_SKIP_DELTAP 0x0000004UL -#define SPH_TWEAK_COURIER_NEW_2_HACK 0x0000008UL -#define SPH_TWEAK_DEEMBOLDEN 0x0000010UL -#define SPH_TWEAK_DO_SHPIX 0x0000020UL -#define SPH_TWEAK_EMBOLDEN 0x0000040UL -#define SPH_TWEAK_MIAP_HACK 0x0000080UL -#define SPH_TWEAK_NORMAL_ROUND 0x0000100UL -#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP 0x0000200UL -#define SPH_TWEAK_NO_CALL_AFTER_IUP 0x0000400UL -#define SPH_TWEAK_NO_DELTAP_AFTER_IUP 0x0000800UL -#define SPH_TWEAK_PIXEL_HINTING 0x0001000UL -#define SPH_TWEAK_RASTERIZER_35 0x0002000UL -#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES 0x0004000UL -#define SPH_TWEAK_SKIP_IUP 0x0008000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES 0x0010000UL -#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES 0x0020000UL -#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK 0x0040000UL -#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP 0x0080000UL - - - FT_LOCAL( FT_Bool ) - sph_test_tweak( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index, - const SPH_TweakRule* rule, - FT_UInt num_rules ); - - FT_LOCAL( FT_UInt ) - sph_test_tweak_x_scaling( TT_Face face, - const FT_String* family, - FT_UInt ppem, - const FT_String* style, - FT_UInt glyph_index ); - - FT_LOCAL( void ) - sph_set_tweaks( TT_Loader loader, - FT_UInt glyph_index ); - - - /* These macros are defined absent a method for setting them */ -#define SPH_OPTION_BITMAP_WIDTHS FALSE -#define SPH_OPTION_SET_SUBPIXEL TRUE -#define SPH_OPTION_SET_GRAYSCALE FALSE -#define SPH_OPTION_SET_COMPATIBLE_WIDTHS FALSE -#define SPH_OPTION_SET_RASTERIZER_VERSION 38 - -#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ - - -FT_END_HEADER - -#endif /* TTSUBPIX_H_ */ - - -/* END */ diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c index a63cd4dc48a..b1a0d23bed6 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h index 7f5cdda191f..92ff627dd0d 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h @@ -4,7 +4,7 @@ * * AFM support for Type 1 fonts (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c index 8ed01914a5a..5ded7714021 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c @@ -4,7 +4,7 @@ * * Type 1 driver interface (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h index 5ff52b55b1a..1cc3d24e7dd 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h @@ -4,7 +4,7 @@ * * High-level Type 1 driver interface (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h index 8aeb24ae188..46bddbc30fd 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h @@ -4,7 +4,7 @@ * * Type 1 error codes (specification only). * - * Copyright (C) 2001-2024 by + * Copyright (C) 2001-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c index c29e682510c..b9bc0b56ce8 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -70,8 +70,13 @@ /* For incremental fonts get the character data using the */ /* callback function. */ if ( inc ) + { + /* So `free_glyph_data` knows whether to free it. */ + char_string->pointer = NULL; + error = inc->funcs->get_glyph_data( inc->object, glyph_index, char_string ); + } else #endif /* FT_CONFIG_OPTION_INCREMENTAL */ @@ -155,6 +160,9 @@ decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); } + if ( error && inc ) + inc->funcs->free_glyph_data( inc->object, char_string ); + #endif /* FT_CONFIG_OPTION_INCREMENTAL */ return error; @@ -295,7 +303,7 @@ { advances[nn] = 0; - FT_TRACE5(( " idx %d: advance height 0 font units\n", + FT_TRACE5(( " idx %u: advance height 0 font units\n", first + nn )); } @@ -333,7 +341,7 @@ else advances[nn] = 0; - FT_TRACE5(( " idx %d: advance width %ld font unit%s\n", + FT_TRACE5(( " idx %u: advance width %ld font unit%s\n", first + nn, advances[nn], advances[nn] == 1 ? "" : "s" )); @@ -380,7 +388,7 @@ goto Exit; } - FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index )); + FT_TRACE1(( "T1_Load_Glyph: glyph index %u\n", glyph_index )); FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); @@ -398,16 +406,12 @@ glyph->y_scale = 0x10000L; } - t1glyph->outline.n_points = 0; - t1glyph->outline.n_contours = 0; - hinting = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) && !( load_flags & FT_LOAD_NO_HINTING ) ); scaled = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) ); glyph->hint = hinting; glyph->scaled = scaled; - t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; error = decoder_funcs->init( &decoder, t1glyph->face, @@ -452,16 +456,12 @@ must_finish_decoder = FALSE; - /* now, set the metrics -- this is rather simple, as */ - /* the left side bearing is the xMin, and the top side */ - /* bearing the yMax */ if ( !error ) { - t1glyph->outline.flags &= FT_OUTLINE_OWNER; - t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; - - /* for composite glyphs, return only left side bearing and */ - /* advance width */ + /* now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax; for composite glyphs, return only */ + /* left side bearing and advance width */ if ( load_flags & FT_LOAD_NO_RECURSE ) { FT_Slot_Internal internal = t1glyph->internal; @@ -482,6 +482,13 @@ FT_Glyph_Metrics* metrics = &t1glyph->metrics; + t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; + + t1glyph->outline.flags &= FT_OUTLINE_OWNER; + t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; + if ( t1size && t1size->metrics.y_ppem < 24 ) + t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; + /* copy the _unscaled_ advance width */ metrics->horiAdvance = FIXED_TO_INT( decoder.builder.advance.x ); @@ -504,11 +511,6 @@ FIXED_TO_INT( decoder.builder.advance.y ); } - t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; - - if ( t1size && t1size->metrics.y_ppem < 24 ) - t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; - #if 1 /* apply the font matrix, if any */ if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h index 17a6a5941e3..6bedd132c5f 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h @@ -4,7 +4,7 @@ * * Type 1 Glyph Loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c index ee7fb42a517..0f11445bef0 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c @@ -4,7 +4,7 @@ * * Type 1 font loader (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, @@ -471,7 +471,7 @@ nc = num_coords; if ( num_coords > blend->num_axis ) { - FT_TRACE2(( "T1_Get_MM_Blend: only using first %d of %d coordinates\n", + FT_TRACE2(( "T1_Get_MM_Blend: only using first %u of %u coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } @@ -640,7 +640,7 @@ { FT_UNUSED( instance_index ); - return T1_Set_MM_Blend( face, 0, NULL ); + return T1_Set_MM_WeightVector( face, 0, NULL ); } @@ -691,7 +691,7 @@ if ( num_coords > blend->num_axis ) { FT_TRACE2(( "T1_Get_Var_Design:" - " only using first %d of %d coordinates\n", + " only using first %u of %u coordinates\n", blend->num_axis, num_coords )); nc = blend->num_axis; } diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h index a45efa7cb7b..2cd8241968d 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h @@ -4,7 +4,7 @@ * * Type 1 font loader (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c index b1b27c31fe3..7f25208f875 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c @@ -4,7 +4,7 @@ * * Type 1 objects manager (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h index 3809370c1e0..6c71977c154 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h @@ -4,7 +4,7 @@ * * Type 1 objects manager (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c index 3717ea7c572..ef643e298f4 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c @@ -4,7 +4,7 @@ * * Type 1 parser (body). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h index a0a2134d45c..f4ad426e9e1 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h @@ -4,7 +4,7 @@ * * Type 1 parser (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h index 5a3d2f1ef08..c3736cd42c0 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h @@ -4,7 +4,7 @@ * * Type 1 tokenizer (specification). * - * Copyright (C) 1996-2024 by + * Copyright (C) 1996-2025 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used, diff --git a/test/jdk/javax/swing/text/html/CSS/8231286/HtmlFontSizeTest.java b/test/jdk/javax/swing/text/html/CSS/8231286/HtmlFontSizeTest.java index 9bdf4dbfae8..eea0a969e77 100644 --- a/test/jdk/javax/swing/text/html/CSS/8231286/HtmlFontSizeTest.java +++ b/test/jdk/javax/swing/text/html/CSS/8231286/HtmlFontSizeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,8 +51,8 @@ public class HtmlFontSizeTest { htmlPane.setEditorKit(kit); String htmlString = "\n" - + "\n" - + "

This should be 16 pt.

\n" + + "\n" + + "

This should be 32 pt.

\n" + "\n" + ""; @@ -71,10 +71,16 @@ public class HtmlFontSizeTest { System.out.println("size with W3C:" + w3cFrameSize); System.out.println("size without W3C:" + stdFrameSize); - float ratio = (float)w3cFrameSize.width / (float)stdFrameSize.width; - System.out.println("w3cFrameSize.width/stdFrameSize.width " + ratio); + float widthRatio = (float)w3cFrameSize.width / (float)stdFrameSize.width; + System.out.println("w3cFrameSize.width/stdFrameSize.width " + widthRatio); - if (!"1.3".equals(String.format(Locale.ENGLISH, "%.1f", ratio))) { + float heightRatio = (float)w3cFrameSize.height / (float)stdFrameSize.height; + System.out.println("w3cFrameSize.height/stdFrameSize.height " + heightRatio); + + float avgRatio = (widthRatio + heightRatio) / 2.0f; + System.out.println("Average ratio of two dimensions " + avgRatio); + + if (!"1.3".equals(String.format(Locale.ENGLISH, "%.1f", avgRatio))) { throw new RuntimeException("HTML font size too large with high-DPI scaling and W3C_LENGTH_UNITS"); } } From 667404948c1c967daf6e274c61b9d1b1bd0827d4 Mon Sep 17 00:00:00 2001 From: Oli Gillespie Date: Tue, 3 Mar 2026 10:05:14 +0000 Subject: [PATCH 026/170] 8378963: Test test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java#id4 failed Reviewed-by: kevinw, dholmes --- .../jdk/java/lang/management/RuntimeMXBean/InputArgument.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java b/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java index 0e7609b86ed..8f0ed8e48af 100644 --- a/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java +++ b/test/jdk/java/lang/management/RuntimeMXBean/InputArgument.java @@ -69,7 +69,7 @@ * * @run driver InputArgument generateFlagsFile * @run main/othervm -XX:+UseFastJNIAccessors -XX:Flags=InputArgument.flags InputArgument - * -XX:+UseFastJNIAccessors -XX:-UseG1GC -XX:+UseParallelGC -XX:MaxHeapSize=100M + * -XX:+UseFastJNIAccessors -XX:+PrintWarnings -XX:-PrintCommandLineFlags -XX:ErrorLogTimeout=100 */ import java.lang.management.*; @@ -116,6 +116,6 @@ public class InputArgument { private static void generateFlagsFile() throws Exception { // 3 types of flag; both boolean cases and 1 numeric Files.writeString(Paths.get("", "InputArgument.flags"), - String.format("-UseG1GC%n+UseParallelGC%nMaxHeapSize=100M%n")); + String.format("+PrintWarnings%n-PrintCommandLineFlags%nErrorLogTimeout=100%n")); } } From b28568f5d8308170c018651ea1c87c2b8f36acb2 Mon Sep 17 00:00:00 2001 From: Vic Wang Date: Tue, 3 Mar 2026 10:41:47 +0000 Subject: [PATCH 027/170] 8367478: Improve UseAVX setting and add cpu descriptions for zhaoxin processors Reviewed-by: jiefu, dholmes --- src/hotspot/cpu/x86/vm_version_x86.cpp | 40 ++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 78d6dec08cf..b352de77d6f 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -958,9 +958,17 @@ void VM_Version::get_processor_features() { if (UseSSE < 1) _features.clear_feature(CPU_SSE); - //since AVX instructions is slower than SSE in some ZX cpus, force USEAVX=0. - if (is_zx() && ((cpu_family() == 6) || (cpu_family() == 7))) { - UseAVX = 0; + // ZX cpus specific settings + if (is_zx() && FLAG_IS_DEFAULT(UseAVX)) { + if (cpu_family() == 7) { + if (extended_cpu_model() == 0x5B || extended_cpu_model() == 0x6B) { + UseAVX = 1; + } else if (extended_cpu_model() == 0x1B || extended_cpu_model() == 0x3B) { + UseAVX = 0; + } + } else if (cpu_family() == 6) { + UseAVX = 0; + } } // UseSSE is set to the smaller of what hardware supports and what @@ -2623,6 +2631,23 @@ const char* VM_Version::cpu_family_description(void) { return _family_id_intel[cpu_family_id]; } } + if (is_zx()) { + int cpu_model_id = extended_cpu_model(); + if (cpu_family_id == 7) { + switch (cpu_model_id) { + case 0x1B: + return "wudaokou"; + case 0x3B: + return "lujiazui"; + case 0x5B: + return "yongfeng"; + case 0x6B: + return "shijidadao"; + } + } else if (cpu_family_id == 6) { + return "zhangjiang"; + } + } if (is_hygon()) { return "Dhyana"; } @@ -2642,6 +2667,9 @@ int VM_Version::cpu_type_description(char* const buf, size_t buf_len) { } else if (is_amd()) { cpu_type = "AMD"; x64 = cpu_is_em64t() ? " AMD64" : ""; + } else if (is_zx()) { + cpu_type = "Zhaoxin"; + x64 = cpu_is_em64t() ? " x86_64" : ""; } else if (is_hygon()) { cpu_type = "Hygon"; x64 = cpu_is_em64t() ? " AMD64" : ""; @@ -3259,6 +3287,12 @@ int VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) { } else { return 128; // Athlon } + } else if (is_zx()) { + if (supports_sse2()) { + return 256; + } else { + return 128; + } } else { // Intel if (supports_sse3() && is_intel_server_family()) { if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus From 7dc97af89f0965ff9e0fa38426adcfc8c69c34ea Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Tue, 3 Mar 2026 12:37:05 +0000 Subject: [PATCH 028/170] 8378905: RISC-V: fastdebug build fails after JDK-8377554 Reviewed-by: fyang, wenanjian --- src/hotspot/cpu/riscv/riscv.ad | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 730dd68dd88..ed6e8db0606 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -2274,7 +2274,7 @@ encode %{ } else if (rtype == relocInfo::metadata_type) { __ mov_metadata(dst_reg, (Metadata*)con); } else { - assert(rtype == relocInfo::none, "unexpected reloc type"); + assert(rtype == relocInfo::none || rtype == relocInfo::external_word_type, "unexpected reloc type"); __ mv(dst_reg, $src$$constant); } } From 6cf8b2ea2fb34b2e63a44d74ffe0495669ea5690 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 3 Mar 2026 13:26:20 +0000 Subject: [PATCH 029/170] 8378845: Add NoSafepointVerifier to CriticalSection classes Reviewed-by: dholmes, iwalulya --- src/hotspot/share/utilities/globalCounter.inline.hpp | 7 +++++-- src/hotspot/share/utilities/singleWriterSynchronizer.hpp | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/utilities/globalCounter.inline.hpp b/src/hotspot/share/utilities/globalCounter.inline.hpp index ed37b8a878d..0d05096716a 100644 --- a/src/hotspot/share/utilities/globalCounter.inline.hpp +++ b/src/hotspot/share/utilities/globalCounter.inline.hpp @@ -29,6 +29,7 @@ #include "runtime/atomic.hpp" #include "runtime/javaThread.hpp" +#include "runtime/safepointVerifiers.hpp" inline GlobalCounter::CSContext GlobalCounter::critical_section_begin(Thread *thread) { @@ -53,11 +54,13 @@ GlobalCounter::critical_section_end(Thread *thread, CSContext context) { } class GlobalCounter::CriticalSection { - private: + NoSafepointVerifier _nsv; Thread* _thread; CSContext _context; - public: + +public: inline CriticalSection(Thread* thread) : + _nsv(), _thread(thread), _context(GlobalCounter::critical_section_begin(_thread)) {} diff --git a/src/hotspot/share/utilities/singleWriterSynchronizer.hpp b/src/hotspot/share/utilities/singleWriterSynchronizer.hpp index 450c7e89233..c21c9d4ee5e 100644 --- a/src/hotspot/share/utilities/singleWriterSynchronizer.hpp +++ b/src/hotspot/share/utilities/singleWriterSynchronizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "memory/allocation.hpp" #include "runtime/atomic.hpp" +#include "runtime/safepointVerifiers.hpp" #include "runtime/semaphore.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -101,12 +102,14 @@ inline void SingleWriterSynchronizer::exit(uint enter_value) { } class SingleWriterSynchronizer::CriticalSection : public StackObj { + NoSafepointVerifier _nsv; SingleWriterSynchronizer* _synchronizer; uint _enter_value; public: // Enter synchronizer's critical section. explicit CriticalSection(SingleWriterSynchronizer* synchronizer) : + _nsv(), _synchronizer(synchronizer), _enter_value(synchronizer->enter()) {} From 364fd0e37e05b98042db9c7c140c5ed6d78b50e0 Mon Sep 17 00:00:00 2001 From: Oli Gillespie Date: Tue, 3 Mar 2026 15:23:08 +0000 Subject: [PATCH 030/170] 8378971: Test jdk/jfr/event/runtime/TestVMInfoEvent.java fails after JDK-8378110 (RuntimeMXBean.getInputArguments()) Reviewed-by: syan, kevinw --- .../jdk/jfr/event/runtime/TestVMInfoEvent.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java b/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java index 2571530a470..8cbc6ea2bb8 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,8 +28,9 @@ import java.lang.management.RuntimeMXBean; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; -import java.util.stream.Collectors; +import java.util.Properties; +import jdk.internal.vm.VMSupport; import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.Asserts; @@ -38,6 +39,7 @@ import jdk.test.lib.jfr.Events; /** * @test + * @modules java.base/jdk.internal.vm * @requires vm.flagless * @requires vm.gc == "Serial" | vm.gc == null * @requires vm.hasJFR @@ -69,13 +71,12 @@ public class TestVMInfoEvent { Asserts.fail(String.format("%s does not contain %s", jvmVersion, mbean.getVmVersion())); } - String jvmArgs = Events.assertField(event, "jvmArguments").notNull().getValue(); - String jvmFlags = Events.assertField(event, "jvmFlags").notNull().getValue(); Long pid = Events.assertField(event, "pid").atLeast(0L).getValue(); Asserts.assertEquals(pid, ProcessHandle.current().pid()); - String eventArgs = (jvmFlags.trim() + " " + jvmArgs).trim(); - String beanArgs = mbean.getInputArguments().stream().collect(Collectors.joining(" ")); - Asserts.assertEquals(eventArgs, beanArgs, "Wrong inputArgs"); + + Properties agentProps = VMSupport.getAgentProperties(); + Events.assertField(event, "jvmArguments").equal(agentProps.getProperty("sun.jvm.args")); + Events.assertField(event, "jvmFlags").equal(agentProps.getProperty("sun.jvm.flags")); final String javaCommand = mbean.getSystemProperties().get("sun.java.command"); Events.assertField(event, "javaArguments").equal(javaCommand); From 0ea7d890d98eda32912e9a8340020ee405042576 Mon Sep 17 00:00:00 2001 From: Raffaello Giulietti Date: Tue, 3 Mar 2026 16:57:09 +0000 Subject: [PATCH 031/170] 8377903: ArraysSupport::mismatch should document that they return the smallest index Reviewed-by: rriggs, vyazici --- .../classes/jdk/internal/util/ArraysSupport.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java index c220455e80b..3bd2486fa39 100644 --- a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java @@ -478,7 +478,7 @@ public class ArraysSupport { // Bytes /** - * Find the index of a mismatch between two arrays. + * Find the smallest index of a mismatch between two arrays. * *

This method does not perform bounds checks. It is the responsibility * of the caller to perform such bounds checks before calling this method. @@ -486,9 +486,9 @@ public class ArraysSupport { * @param a the first array to be tested for a mismatch * @param b the second array to be tested for a mismatch * @param length the number of bytes from each array to check - * @return the index of a mismatch between the two arrays, otherwise -1 if - * no mismatch. The index will be within the range of (inclusive) 0 to - * (exclusive) the smaller of the two array lengths. + * @return the smallest index of a mismatch between the two arrays, + * otherwise -1 if no mismatch. The index will be within the range of + * (inclusive) 0 to (exclusive) the smaller of the two array lengths. */ public static int mismatch(byte[] a, byte[] b, @@ -520,8 +520,8 @@ public class ArraysSupport { } /** - * Find the relative index of a mismatch between two arrays starting from - * given indexes. + * Find the smallest relative index of a mismatch between two arrays + * starting from given indexes. * *

This method does not perform bounds checks. It is the responsibility * of the caller to perform such bounds checks before calling this method. @@ -533,7 +533,7 @@ public class ArraysSupport { * @param bFromIndex the index of the first element (inclusive) in the * second array to be compared * @param length the number of bytes from each array to check - * @return the relative index of a mismatch between the two arrays, + * @return the smallest relative index of a mismatch between the two arrays, * otherwise -1 if no mismatch. The index will be within the range of * (inclusive) 0 to (exclusive) the smaller of the two array bounds. */ From df43ef915ab13714c7a191c6413494f97f9db8c2 Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Tue, 3 Mar 2026 17:09:14 +0000 Subject: [PATCH 032/170] 8378883: Enable more vector reductions IR matching tests for RISC-V Reviewed-by: fyang --- .../loopopts/superword/TestReductions.java | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestReductions.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestReductions.java index 9d674950499..5c085e6a3a3 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestReductions.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestReductions.java @@ -1340,7 +1340,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.AND_REDUCTION_V, "> 0", IRNode.AND_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1357,7 +1357,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.OR_REDUCTION_V, "> 0", IRNode.OR_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1374,7 +1374,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.XOR_REDUCTION_V, "> 0", IRNode.XOR_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1391,7 +1391,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.ADD_REDUCTION_VI, "> 0", IRNode.ADD_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1408,7 +1408,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_REDUCTION_VI, "> 0", IRNode.MUL_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1425,7 +1425,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1442,7 +1442,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1460,7 +1460,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.AND_REDUCTION_V, "> 0", IRNode.AND_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1477,7 +1477,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.OR_REDUCTION_V, "> 0", IRNode.OR_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1494,7 +1494,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.XOR_REDUCTION_V, "> 0", IRNode.XOR_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1511,7 +1511,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.ADD_REDUCTION_VI, "> 0", IRNode.ADD_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1528,7 +1528,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_REDUCTION_VI, "> 0", IRNode.MUL_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1545,7 +1545,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1562,7 +1562,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1580,7 +1580,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.AND_REDUCTION_V, "> 0", IRNode.AND_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1597,7 +1597,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.OR_REDUCTION_V, "> 0", IRNode.OR_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1614,7 +1614,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.XOR_REDUCTION_V, "> 0", IRNode.XOR_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1631,7 +1631,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.ADD_REDUCTION_VI, "> 0", IRNode.ADD_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1648,7 +1648,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_REDUCTION_VI, "> 0", IRNode.MUL_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1665,7 +1665,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1682,7 +1682,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_I, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1700,7 +1700,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.AND_REDUCTION_V, "> 0", IRNode.AND_VL, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_L, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1717,7 +1717,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.OR_REDUCTION_V, "> 0", IRNode.OR_VL, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_L, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1734,7 +1734,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.XOR_REDUCTION_V, "> 0", IRNode.XOR_VL, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_L, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1751,7 +1751,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_REDUCTION_VL, "> 0", IRNode.ADD_VL, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_L, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -1799,7 +1799,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VL, "> 0"}, - applyIfCPUFeatureOr = {"avx512", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx512", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_L, applyIfCPUFeatureAnd = {"avx512", "false", "avx2", "true"}) @@ -1819,7 +1819,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VL, "> 0"}, - applyIfCPUFeatureOr = {"avx512", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx512", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_L, applyIfCPUFeatureAnd = {"avx512", "false", "avx2", "true"}) @@ -2207,7 +2207,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VF, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_F, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2224,7 +2224,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VF, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_F, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2284,7 +2284,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VF, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_F, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2301,7 +2301,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VF, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_F, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2361,7 +2361,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VF, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_F, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2378,7 +2378,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VF, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_F, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2444,7 +2444,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VD, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_D, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2461,7 +2461,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VD, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_D, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2521,7 +2521,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VD, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_D, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2538,7 +2538,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VD, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_D, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2598,7 +2598,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.MIN_VD, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_D, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) @@ -2615,7 +2615,7 @@ public class TestReductions { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MAX_REDUCTION_V, "> 0", IRNode.MAX_VD, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, applyIf = {"AutoVectorizationOverrideProfitability", "> 0"}) @IR(failOn = IRNode.LOAD_VECTOR_D, applyIf = {"AutoVectorizationOverrideProfitability", "= 0"}) From 86800eb2b34bd6ea7a77e7a9ac2f7dbce89c11fb Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Tue, 3 Mar 2026 17:11:17 +0000 Subject: [PATCH 033/170] 8378723: Locale variant delimiter is unclear Reviewed-by: naoto --- src/java.base/share/classes/java/util/Locale.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index f45a52c14fa..682476d8082 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -176,7 +176,10 @@ import sun.util.locale.provider.TimeZoneNameUtility; * SUBTAG (('_'|'-') SUBTAG)*} where {@code SUBTAG = * [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}}. *

BCP 47 deviation: BCP 47 only - * uses hyphen ('-') as a delimiter, {@code Locale} is more lenient.
+ * uses hyphen ('-') as a delimiter and APIs provided by {@code Locale} which accept + * BCP 47 language tags expect as such. However, for backwards compatibility, + * {@link Locale.Builder#setVariant(String)} also accepts underscore ('_'). + * {@link Locale#of(String, String, String)} accepts only underscore ('_'). * *
Example: "polyton" (Polytonic Greek), "POSIX"
* From c13fdc044d188d2266b2a96c4d1803b014a00633 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 3 Mar 2026 19:09:03 +0000 Subject: [PATCH 034/170] 8378877: jpackage: improve rebranding of exe files on Windows Reviewed-by: almatvee --- .../internal/ExecutableRebrander.java | 142 +++++++++++------- .../jpackage/internal/WindowsDefender.java | 72 --------- .../jpackage/internal/WindowsRegistry.java | 130 ---------------- .../resources/WinResources.properties | 1 - 4 files changed, 87 insertions(+), 258 deletions(-) delete mode 100644 src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsDefender.java delete mode 100644 src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsRegistry.java diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java index 05b87e6f449..ec2a96d4c7d 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,9 +40,11 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Properties; +import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Stream; import jdk.jpackage.internal.model.DottedVersion; +import jdk.jpackage.internal.model.JPackageException; import jdk.jpackage.internal.model.WinApplication; import jdk.jpackage.internal.model.WinExePackage; import jdk.jpackage.internal.model.WinLauncher; @@ -74,11 +76,11 @@ final class ExecutableRebrander { this.props = new HashMap<>(); - validateValueAndPut(this.props, Map.entry("COMPANY_NAME", props.vendor), "vendor"); - validateValueAndPut(this.props, Map.entry("FILE_DESCRIPTION",props.description), "description"); - validateValueAndPut(this.props, Map.entry("FILE_VERSION", props.version.toString()), "version"); - validateValueAndPut(this.props, Map.entry("LEGAL_COPYRIGHT", props.copyright), "copyright"); - validateValueAndPut(this.props, Map.entry("PRODUCT_NAME", props.name), "name"); + this.props.put("COMPANY_NAME", validateSingleLine(props.vendor)); + this.props.put("FILE_DESCRIPTION", validateSingleLine(props.description)); + this.props.put("FILE_VERSION", validateSingleLine(props.version.toString())); + this.props.put("LEGAL_COPYRIGHT", validateSingleLine(props.copyright)); + this.props.put("PRODUCT_NAME", validateSingleLine(props.name)); this.props.put("FIXEDFILEINFO_FILE_VERSION", toFixedFileVersion(props.version)); this.props.put("INTERNAL_NAME", props.executableName); @@ -90,7 +92,7 @@ final class ExecutableRebrander { UpdateResourceAction versionSwapper = resourceLock -> { if (versionSwap(resourceLock, propsArray) != 0) { - throw I18N.buildException().message("error.version-swap", target).create(RuntimeException::new); + throw new JPackageException(I18N.format("error.version-swap", target)); } }; @@ -100,7 +102,7 @@ final class ExecutableRebrander { .map(absIcon -> { return resourceLock -> { if (iconSwap(resourceLock, absIcon.toString()) != 0) { - throw I18N.buildException().message("error.icon-swap", absIcon).create(RuntimeException::new); + throw new JPackageException(I18N.format("error.icon-swap", absIcon)); } }; }); @@ -118,43 +120,58 @@ final class ExecutableRebrander { private static void rebrandExecutable(BuildEnv env, final Path target, List actions) throws IOException { + + Objects.requireNonNull(env); + Objects.requireNonNull(target); Objects.requireNonNull(actions); actions.forEach(Objects::requireNonNull); - String tempDirectory = env.buildRoot().toAbsolutePath().toString(); - if (WindowsDefender.isThereAPotentialWindowsDefenderIssue(tempDirectory)) { - Log.verbose(I18N.format("message.potential.windows.defender.issue", tempDirectory)); - } - - var shortTargetPath = ShortPathUtils.toShortPath(target); - long resourceLock = lockResource(shortTargetPath.orElse(target).toString()); - if (resourceLock == 0) { - throw I18N.buildException().message("error.lock-resource", shortTargetPath.orElse(target)).create(RuntimeException::new); - } - - final boolean resourceUnlockedSuccess; try { - for (var action : actions) { - action.editResource(resourceLock); - } - } finally { - if (resourceLock == 0) { - resourceUnlockedSuccess = true; - } else { - resourceUnlockedSuccess = unlockResource(resourceLock); - if (shortTargetPath.isPresent()) { - // Windows will rename the executable in the unlock operation. - // Should restore executable's name. - var tmpPath = target.getParent().resolve( - target.getFileName().toString() + ".restore"); - Files.move(shortTargetPath.get(), tmpPath); - Files.move(tmpPath, target); - } - } - } + Globals.instance().objectFactory().retryExecutor(RuntimeException.class).setExecutable(() -> { - if (!resourceUnlockedSuccess) { - throw I18N.buildException().message("error.unlock-resource", target).create(RuntimeException::new); + var shortTargetPath = ShortPathUtils.toShortPath(target); + long resourceLock = lockResource(shortTargetPath.orElse(target).toString()); + if (resourceLock == 0) { + throw new JPackageException(I18N.format("error.lock-resource", shortTargetPath.orElse(target))); + } + + final boolean resourceUnlockedSuccess; + try { + for (var action : actions) { + try { + action.editResource(resourceLock); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + } finally { + if (resourceLock == 0) { + resourceUnlockedSuccess = true; + } else { + resourceUnlockedSuccess = unlockResource(resourceLock); + if (shortTargetPath.isPresent()) { + // Windows will rename the executable in the unlock operation. + // Should restore executable's name. + var tmpPath = target.getParent().resolve( + target.getFileName().toString() + ".restore"); + try { + Files.move(shortTargetPath.get(), tmpPath); + Files.move(tmpPath, target); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + } + } + + if (!resourceUnlockedSuccess) { + throw new JPackageException(I18N.format("error.unlock-resource", shortTargetPath.orElse(target))); + } + + return null; + }).setMaxAttemptsCount(5).setAttemptTimeout(3, TimeUnit.SECONDS).execute(); + } catch (UncheckedIOException ex) { + throw ex.getCause(); } } @@ -197,14 +214,13 @@ final class ExecutableRebrander { } } - private static void validateValueAndPut(Map target, - Map.Entry e, String label) { - if (e.getValue().contains("\r") || e.getValue().contains("\n")) { - Log.error("Configuration parameter " + label - + " contains multiple lines of text, ignore it"); - e = Map.entry(e.getKey(), ""); + private static String validateSingleLine(String v) { + Objects.requireNonNull(v); + if (v.contains("\r") || v.contains("\n")) { + throw new IllegalArgumentException("Configuration parameter contains multiple lines of text"); + } else { + return v; } - target.put(e.getKey(), e.getValue()); } @FunctionalInterface @@ -212,19 +228,35 @@ final class ExecutableRebrander { public void editResource(long resourceLock) throws IOException; } - private static record ExecutableProperties(String vendor, String description, + private record ExecutableProperties(String vendor, String description, DottedVersion version, String copyright, String name, String executableName) { - static ExecutableProperties create(WinApplication app, - WinLauncher launcher) { - return new ExecutableProperties(app.vendor(), launcher.description(), - app.winVersion(), app.copyright(), launcher.name(), + + ExecutableProperties { + Objects.requireNonNull(vendor); + Objects.requireNonNull(description); + Objects.requireNonNull(version); + Objects.requireNonNull(copyright); + Objects.requireNonNull(name); + Objects.requireNonNull(executableName); + } + + static ExecutableProperties create(WinApplication app, WinLauncher launcher) { + return new ExecutableProperties( + app.vendor(), + launcher.description(), + app.winVersion(), + app.copyright(), + launcher.name(), launcher.executableNameWithSuffix()); } static ExecutableProperties create(WinExePackage pkg) { - return new ExecutableProperties(pkg.app().vendor(), - pkg.description(), DottedVersion.lazy(pkg.version()), - pkg.app().copyright(), pkg.packageName(), + return new ExecutableProperties( + pkg.app().vendor(), + pkg.description(), + DottedVersion.lazy(pkg.version()), + pkg.app().copyright(), + pkg.packageName(), pkg.packageFileNameWithSuffix()); } } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsDefender.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsDefender.java deleted file mode 100644 index 075d87bcbca..00000000000 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsDefender.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jpackage.internal; - -import java.util.List; -import jdk.internal.util.OperatingSystem; -import jdk.internal.util.OSVersion; - -final class WindowsDefender { - - private WindowsDefender() {} - - static final boolean isThereAPotentialWindowsDefenderIssue(String dir) { - boolean result = false; - - if (OperatingSystem.isWindows() && - OSVersion.current().major() == 10) { - - // If DisableRealtimeMonitoring is not enabled then there - // may be a problem. - if (!WindowsRegistry.readDisableRealtimeMonitoring() && - !isDirectoryInExclusionPath(dir)) { - result = true; - } - } - - return result; - } - - private static boolean isDirectoryInExclusionPath(String dir) { - boolean result = false; - // If the user temp directory is not found in the exclusion - // list then there may be a problem. - List paths = WindowsRegistry.readExclusionsPaths(); - for (String s : paths) { - if (WindowsRegistry.comparePaths(s, dir)) { - result = true; - break; - } - } - - return result; - } - - static final String getUserTempDirectory() { - String tempDirectory = System.getProperty("java.io.tmpdir"); - return tempDirectory; - } -} diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsRegistry.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsRegistry.java deleted file mode 100644 index 7eb7b922667..00000000000 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsRegistry.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, 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 jdk.jpackage.internal; - -import java.util.ArrayList; -import java.util.List; - -@SuppressWarnings("restricted") -final class WindowsRegistry { - - // Currently we only support HKEY_LOCAL_MACHINE. Native implementation will - // require support for additinal HKEY if needed. - private static final int HKEY_LOCAL_MACHINE = 1; - - static { - System.loadLibrary("jpackage"); - } - - private WindowsRegistry() {} - - /** - * Reads the registry value for DisableRealtimeMonitoring. - * @return true if DisableRealtimeMonitoring is set to 0x1, - * false otherwise. - */ - static final boolean readDisableRealtimeMonitoring() { - final String subKey = "Software\\Microsoft\\" - + "Windows Defender\\Real-Time Protection"; - final String value = "DisableRealtimeMonitoring"; - int result = readDwordValue(HKEY_LOCAL_MACHINE, subKey, value, 0); - return (result == 1); - } - - static final List readExclusionsPaths() { - List result = new ArrayList<>(); - final String subKey = "Software\\Microsoft\\" - + "Windows Defender\\Exclusions\\Paths"; - long lKey = openRegistryKey(HKEY_LOCAL_MACHINE, subKey); - if (lKey == 0) { - return result; - } - - String valueName; - int index = 0; - do { - valueName = enumRegistryValue(lKey, index); - if (valueName != null) { - result.add(valueName); - index++; - } - } while (valueName != null); - - closeRegistryKey(lKey); - - return result; - } - - /** - * Reads DWORD registry value. - * - * @param key one of HKEY predefine value - * @param subKey registry sub key - * @param value value to read - * @param defaultValue default value in case if subKey or value not found - * or any other errors occurred - * @return value's data only if it was read successfully, otherwise - * defaultValue - */ - private static native int readDwordValue(int key, String subKey, - String value, int defaultValue); - - /** - * Open registry key. - * - * @param key one of HKEY predefine value - * @param subKey registry sub key - * @return native handle to open key - */ - private static native long openRegistryKey(int key, String subKey); - - /** - * Enumerates the values for registry key. - * - * @param lKey native handle to open key returned by openRegistryKey - * @param index index of value starting from 0. Increment until this - * function returns NULL which means no more values. - * @return returns value or NULL if error or no more data - */ - private static native String enumRegistryValue(long lKey, int index); - - /** - * Close registry key. - * - * @param lKey native handle to open key returned by openRegistryKey - */ - private static native void closeRegistryKey(long lKey); - - /** - * Compares two Windows paths regardless case and if paths - * are short or long. - * - * @param path1 path to compare - * @param path2 path to compare - * @return true if paths point to same location - */ - public static native boolean comparePaths(String path1, String path2); -} diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties index 38d0bd02bbb..13a6c989324 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties @@ -55,7 +55,6 @@ error.missing-service-installer='service-installer.exe' service installer not fo error.missing-service-installer.advice=Add 'service-installer.exe' service installer to the resource directory message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place. -message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}". message.tool-version=Detected [{0}] version [{1}]. message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required. message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action. From a6db3f870218bc016ecc67e3f5e142d6491ac080 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 3 Mar 2026 19:11:11 +0000 Subject: [PATCH 035/170] 8378873: jpackage: remove macOS-specific code from jdk.jpackage.internal.ModuleInfo Reviewed-by: almatvee --- .../jdk/jpackage/internal/FromOptions.java | 18 +++++++++++++++++- .../jdk/jpackage/internal/ModuleInfo.java | 15 ++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java index cccd05792d6..4f590850328 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromOptions.java @@ -49,6 +49,7 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; @@ -149,6 +150,13 @@ final class FromOptions { ApplicationLayout appLayout, RuntimeLayout runtimeLayout, Optional predefinedRuntimeLayout) { + Objects.requireNonNull(options); + Objects.requireNonNull(launcherCtor); + Objects.requireNonNull(launcherOverrideCtor); + Objects.requireNonNull(appLayout); + Objects.requireNonNull(runtimeLayout); + Objects.requireNonNull(predefinedRuntimeLayout); + final var appBuilder = new ApplicationBuilder(); final var isRuntimeInstaller = isRuntimeInstaller(options); @@ -185,7 +193,15 @@ final class FromOptions { } else { appBuilder.appImageLayout(appLayout); - final var launchers = createLaunchers(options, launcherCtor); + // Adjust the value of the PREDEFINED_RUNTIME_IMAGE option to make it reference + // a directory with the standard Java runtime structure. + final var launcherOptions = predefinedRuntimeDirectory.filter(v -> { + return !predefinedRuntimeImage.get().equals(v); + }).map(v -> { + return Options.of(Map.of(PREDEFINED_RUNTIME_IMAGE, v)).copyWithParent(options); + }).orElse(options); + + final var launchers = createLaunchers(launcherOptions, launcherCtor); if (PREDEFINED_APP_IMAGE.containsIn(options)) { appBuilder.launchers(launchers); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ModuleInfo.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ModuleInfo.java index 590321d5e86..71d1a66659e 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ModuleInfo.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ModuleInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Properties; -import jdk.internal.util.OperatingSystem; record ModuleInfo(String name, Optional version, Optional mainClass, Optional location) { @@ -61,17 +60,7 @@ record ModuleInfo(String name, Optional version, Optional mainCl // is linked in the runtime by simply analysing the data // of `release` file. - final Path releaseFile; - if (!OperatingSystem.isMacOS()) { - releaseFile = cookedRuntime.resolve("release"); - } else { - // On Mac `cookedRuntime` can be runtime root or runtime home. - Path runtimeHome = cookedRuntime.resolve("Contents/Home"); - if (!Files.isDirectory(runtimeHome)) { - runtimeHome = cookedRuntime; - } - releaseFile = runtimeHome.resolve("release"); - } + final Path releaseFile = cookedRuntime.resolve("release"); try (Reader reader = Files.newBufferedReader(releaseFile)) { Properties props = new Properties(); From 73363a0cb501eb10f5be4a6a283b20da58b1950d Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 3 Mar 2026 21:53:20 +0000 Subject: [PATCH 036/170] 8378874: jpackage: remove redundant messages Reviewed-by: almatvee --- .../jdk/jpackage/internal/MacPkgPackager.java | 6 ------ .../internal/resources/MacResources.properties | 1 - .../jdk/jpackage/internal/WinMsiPackager.java | 3 --- .../internal/WixAppImageFragmentBuilder.java | 13 +------------ .../jdk/jpackage/internal/WixFragmentBuilder.java | 9 ++------- .../internal/resources/WinResources.properties | 1 - 6 files changed, 3 insertions(+), 30 deletions(-) diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackager.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackager.java index fc5c85c699c..369ab201611 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackager.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackager.java @@ -51,7 +51,6 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import jdk.internal.util.Architecture; -import jdk.internal.util.OSVersion; import jdk.jpackage.internal.PackagingPipeline.PackageTaskID; import jdk.jpackage.internal.PackagingPipeline.TaskID; import jdk.jpackage.internal.model.MacPkgPackage; @@ -509,11 +508,6 @@ record MacPkgPackager(BuildEnv env, MacPkgPackage pkg, Optional servic // maybe sign if (pkg.sign()) { - if (OSVersion.current().compareTo(new OSVersion(10, 12)) >= 0) { - // we need this for OS X 10.12+ - Log.verbose(I18N.getString("message.signing.pkg")); - } - final var pkgSigningConfig = pkg.signingConfig().orElseThrow(); commandLine.add("--sign"); diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties index 3aebdc39d41..90c4162b80e 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties @@ -61,7 +61,6 @@ message.invalid-identifier.advice=specify identifier with "--mac-package-identif message.preparing-dmg-setup=Preparing dmg setup: {0}. message.preparing-scripts=Preparing package scripts. message.preparing-distribution-dist=Preparing distribution.dist: {0}. -message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool. message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue. message.codesign.failed.reason.app.content="codesign" failed and additional application content was supplied via the "--app-content" parameter. Probably the additional content broke the integrity of the application bundle and caused the failure. Ensure content supplied via the "--app-content" parameter does not break the integrity of the application bundle, or add it in the post-processing step. message.codesign.failed.reason.xcode.tools=Possible reason for "codesign" failure is missing Xcode with command line developer tools. Install Xcode with command line developer tools to see if it resolves the problem. diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiPackager.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiPackager.java index c72b14a76d5..a53d083847a 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiPackager.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiPackager.java @@ -151,9 +151,6 @@ final class WinMsiPackager implements Consumer { wixFragments.forEach(wixFragment -> wixFragment.setWixVersion(wixToolset.getVersion(), wixToolset.getType())); - - wixFragments.stream().map(WixFragmentBuilder::getLoggableWixFeatures).flatMap( - List::stream).distinct().toList().forEach(Log::verbose); } WinMsiPackager(BuildEnv env, WinMsiPackage pkg, Path outputDir, WinSystemEnvironment sysEnv) { diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java index 0dff5c26ae2..ac7af873739 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import static jdk.jpackage.internal.util.CollectionUtils.toCollection; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -142,16 +141,6 @@ final class WixAppImageFragmentBuilder extends WixFragmentBuilder { super.addFilesToConfigRoot(); } - @Override - List getLoggableWixFeatures() { - if (isWithWix36Features()) { - return List.of(MessageFormat.format(I18N.getString("message.use-wix36-features"), - getWixVersion())); - } else { - return List.of(); - } - } - @Override protected Collection getFragmentWriters() { return List.of( diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java index 4d180a94871..46894699d98 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixFragmentBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,19 +30,18 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.nio.file.Path; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.stream.XMLStreamWriter; -import jdk.jpackage.internal.util.XmlConsumer; import jdk.internal.util.Architecture; import jdk.jpackage.internal.WixSourceConverter.ResourceGroup; import jdk.jpackage.internal.WixToolset.WixToolsetType; import jdk.jpackage.internal.model.DottedVersion; import jdk.jpackage.internal.model.WinMsiPackage; +import jdk.jpackage.internal.util.XmlConsumer; import jdk.jpackage.internal.util.XmlUtils; /** @@ -72,10 +71,6 @@ abstract class WixFragmentBuilder { fragmentResource = env.createResource(defaultResourceName).setPublicName(outputFileName); } - List getLoggableWixFeatures() { - return List.of(); - } - void configureWixPipeline(WixPipeline.Builder wixPipeline) { wixPipeline.addSource(configRoot.resolve(outputFileName), Optional.ofNullable(wixVariables).map(WixVariables::getValues).orElse( diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties index 13a6c989324..0f3dcab8260 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties @@ -57,7 +57,6 @@ error.missing-service-installer.advice=Add 'service-installer.exe' service insta message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place. message.tool-version=Detected [{0}] version [{1}]. message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required. -message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action. message.product-code=MSI ProductCode: {0}. message.upgrade-code=MSI UpgradeCode: {0}. message.preparing-msi-config=Preparing MSI config: {0}. From 0729d1d82207de856fdd8d2fe2a2ea4a0b8694a2 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Wed, 4 Mar 2026 00:36:08 +0000 Subject: [PATCH 037/170] 8379039: Build failure on vector API source generation after JDK-8378312 Reviewed-by: jbhateja, psandoz --- .../share/classes/jdk/incubator/vector/X-Vector.java.template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index d6763c2c03a..95fe8ca35db 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -772,7 +772,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { @ForceInline final $abstractvectortype$ unaryMathOp(VectorOperators.Unary op) { - return VectorMathLibrary.unaryMathOp(op, opCode(op), species(), $abstractvectortype$::unaryOperations, + return VectorMathLibrary.unaryMathOp(op, opCode(op), vspecies(), $abstractvectortype$::unaryOperations, this); } #end[FP] @@ -983,7 +983,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { @ForceInline final $abstractvectortype$ binaryMathOp(VectorOperators.Binary op, $abstractvectortype$ that) { - return VectorMathLibrary.binaryMathOp(op, opCode(op), species(), $abstractvectortype$::binaryOperations, + return VectorMathLibrary.binaryMathOp(op, opCode(op), vspecies(), $abstractvectortype$::binaryOperations, this, that); } #end[FP] From 284d1310d059764b5fb887d4693af623c2f7e89a Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Wed, 4 Mar 2026 00:49:05 +0000 Subject: [PATCH 038/170] 8378876: jpackage: facilitate testing with mocks Reviewed-by: almatvee --- .../jpackage/internal/LibProvidersLookup.java | 2 +- .../LinuxDebSystemEnvironmentMixin.java | 3 ++ .../LinuxRpmSystemEnvironmentMixin.java | 4 +- .../internal/MacBundlingEnvironment.java | 5 +++ .../internal/MacDmgSystemEnvironment.java | 23 ++++++++--- .../jdk/jpackage/internal/AppImageFile.java | 13 ------- .../internal/DefaultBundlingEnvironment.java | 9 +++++ .../jpackage/internal/OptionsTransformer.java | 7 +++- .../jdk/jpackage/internal/PackageBuilder.java | 22 ++++++----- .../jdk/jpackage/internal/ToolValidator.java | 4 -- .../jdk/jpackage/internal/cli/Main.java | 39 +++++++++++-------- .../internal/cli/OptionsAnalyzer.java | 12 +++--- .../internal/cli/OptionsProcessor.java | 6 ++- .../jpackage/internal/cli/StandardOption.java | 6 +++ .../jdk/jpackage/test/AppImageFile.java | 16 ++++---- .../helpers/jdk/jpackage/test/JavaTool.java | 5 ++- .../helpers/jdk/jpackage/test/TKit.java | 39 +++++++++++++++---- .../test/stdmock/JPackageMockUtils.java | 2 +- .../jpackage/internal/AppImageFileTest.java | 16 +++++--- .../jdk/jpackage/internal/cli/MainTest.java | 6 ++- .../internal/cli/OptionsProcessorTest.java | 4 +- .../cli/OptionsValidationFailTest.java | 2 +- 22 files changed, 157 insertions(+), 88 deletions(-) diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LibProvidersLookup.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LibProvidersLookup.java index 6faacbca528..2dccc91cf8f 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LibProvidersLookup.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LibProvidersLookup.java @@ -44,7 +44,7 @@ import java.util.stream.Stream; */ public final class LibProvidersLookup { static boolean supported() { - return (new ToolValidator(TOOL_LDD).validate() == null); + return (new ToolValidator(TOOL_LDD).setCommandLine("--version").validate() == null); } LibProvidersLookup setPackageLookup(PackageLookup v) { diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebSystemEnvironmentMixin.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebSystemEnvironmentMixin.java index 2cf3e9e36e8..4c6fd75bed8 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebSystemEnvironmentMixin.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebSystemEnvironmentMixin.java @@ -40,6 +40,9 @@ interface LinuxDebSystemEnvironmentMixin { static Result create() { final var errors = Stream.of(Internal.TOOL_DPKG_DEB, Internal.TOOL_DPKG, Internal.TOOL_FAKEROOT) .map(ToolValidator::new) + .map(v -> { + return v.setCommandLine("--version"); + }) .map(ToolValidator::validate) .filter(Objects::nonNull) .toList(); diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmSystemEnvironmentMixin.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmSystemEnvironmentMixin.java index 4cbd3ce4a9c..8de28b79430 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmSystemEnvironmentMixin.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmSystemEnvironmentMixin.java @@ -44,7 +44,9 @@ interface LinuxRpmSystemEnvironmentMixin { final var errors = Stream.of( Internal.createRpmbuildToolValidator(), new ToolValidator(Internal.TOOL_RPM) - ).map(ToolValidator::validate).filter(Objects::nonNull).toList(); + ).map(v -> { + return v.setCommandLine("--version"); + }).map(ToolValidator::validate).filter(Objects::nonNull).toList(); if (errors.isEmpty()) { return Result.ofValue(new Stub(Internal.TOOL_RPM, Internal.TOOL_RPMBUILD)); diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBundlingEnvironment.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBundlingEnvironment.java index 224ea20f249..1e60d8490f0 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBundlingEnvironment.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBundlingEnvironment.java @@ -31,6 +31,7 @@ import static jdk.jpackage.internal.cli.StandardBundlingOperation.CREATE_MAC_APP import static jdk.jpackage.internal.cli.StandardBundlingOperation.CREATE_MAC_DMG; import static jdk.jpackage.internal.cli.StandardBundlingOperation.CREATE_MAC_PKG; import static jdk.jpackage.internal.cli.StandardBundlingOperation.SIGN_MAC_APP_IMAGE; +import static jdk.jpackage.internal.cli.StandardOption.EXIT_AFTER_CONFIGURATION_PHASE; import java.util.Optional; import jdk.jpackage.internal.cli.Options; @@ -74,6 +75,10 @@ public class MacBundlingEnvironment extends DefaultBundlingEnvironment { final var pkg = createSignAppImagePackage(app, env); + if (EXIT_AFTER_CONFIGURATION_PHASE.getFrom(options)) { + return; + } + buildPipeline(pkg).create().execute(env, pkg, env.appImageDir()); } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgSystemEnvironment.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgSystemEnvironment.java index 12d105b99b5..11cf94ca66d 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgSystemEnvironment.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgSystemEnvironment.java @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.internal.util.OperatingSystem; import jdk.jpackage.internal.util.Result; record MacDmgSystemEnvironment(Path hdiutil, Path osascript, Optional setFileUtility) implements SystemEnvironment { @@ -39,12 +40,22 @@ record MacDmgSystemEnvironment(Path hdiutil, Path osascript, Optional setF } static Result create() { - final var errors = Stream.of(HDIUTIL, OSASCRIPT) - .map(ToolValidator::new) - .map(ToolValidator::checkExistsOnly) - .map(ToolValidator::validate) - .filter(Objects::nonNull) - .toList(); + + List errors; + + if (OperatingSystem.isMacOS()) { + errors = Stream.of(HDIUTIL, OSASCRIPT) + .map(ToolValidator::new) + .map(ToolValidator::checkExistsOnly) + .map(ToolValidator::validate) + .filter(Objects::nonNull) + .toList(); + } else { + // The code runs on an OS other than macOS. Presume this is mock testing. + // Don't validate the tools; checking that their executables exist will fail in this environment. + errors = List.of(); + } + if (errors.isEmpty()) { return Result.ofValue(new MacDmgSystemEnvironment(HDIUTIL, OSASCRIPT, findSetFileUtility())); } else { diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java index 75ead9d08ad..7edc6cd3c11 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java @@ -134,19 +134,6 @@ final class AppImageFile { return appLayout.appDirectory().resolve(FILENAME); } - /** - * Loads application image info from the specified application layout. - *

- * It is an equivalent to calling - * {@link #load(ApplicationLayout, OperatingSystem)} method with - * {@code OperatingSystem.current()} for the second parameter. - * - * @param appLayout the application layout - */ - static ExternalApplication load(ApplicationLayout appLayout) { - return load(appLayout, OperatingSystem.current()); - } - /** * Loads application image info from the specified application layout and OS. * diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/DefaultBundlingEnvironment.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/DefaultBundlingEnvironment.java index fc51f60aa66..ae4b1005318 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/DefaultBundlingEnvironment.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/DefaultBundlingEnvironment.java @@ -25,6 +25,7 @@ package jdk.jpackage.internal; import static java.util.stream.Collectors.toMap; +import static jdk.jpackage.internal.cli.StandardOption.EXIT_AFTER_CONFIGURATION_PHASE; import static jdk.jpackage.internal.util.MemoizingSupplier.runOnce; import java.io.IOException; @@ -129,6 +130,10 @@ class DefaultBundlingEnvironment implements CliBundlingEnvironment { Objects.requireNonNull(app); Objects.requireNonNull(pipelineBuilder); + if (EXIT_AFTER_CONFIGURATION_PHASE.getFrom(options)) { + return; + } + final var outputDir = PathUtils.normalizedAbsolutePath(OptionUtils.outputDir(options).resolve(app.appImageDirName())); Log.verbose(I18N.getString("message.create-app-image")); @@ -170,6 +175,10 @@ class DefaultBundlingEnvironment implements CliBundlingEnvironment { Objects.requireNonNull(createPipelineBuilder); Objects.requireNonNull(pipelineBuilderMutatorFactory); + if (EXIT_AFTER_CONFIGURATION_PHASE.getFrom(options)) { + return; + } + var pipelineBuilder = Objects.requireNonNull(createPipelineBuilder.apply(pkg)); // Delete an old output package file (if any) before creating a new one. diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OptionsTransformer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OptionsTransformer.java index a01be089a49..f7b535b06f6 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OptionsTransformer.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OptionsTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,10 @@ record OptionsTransformer(Options mainOptions, Optional ext } OptionsTransformer(Options mainOptions, ApplicationLayout appLayout) { - this(mainOptions, PREDEFINED_APP_IMAGE.findIn(mainOptions).map(appLayout::resolveAt).map(AppImageFile::load)); + this(mainOptions, PREDEFINED_APP_IMAGE.findIn(mainOptions).map(appLayout::resolveAt).map(resolvedLayout -> { + var os = OptionUtils.bundlingOperation(mainOptions).os(); + return AppImageFile.load(resolvedLayout, os); + })); } Options appOptions() { diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackageBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackageBuilder.java index f537a1ea0a2..8b61ef19fa2 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackageBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackageBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -207,7 +207,7 @@ final class PackageBuilder { }); } - private static Path mapInstallDir(Path installDir, PackageType pkgType) { + private static Path mapInstallDir(Path installDir, PackageType type) { var ex = buildConfigException("error.invalid-install-dir", installDir).create(); if (installDir.getNameCount() == 0) { @@ -223,15 +223,17 @@ final class PackageBuilder { throw ex; } - switch (pkgType) { - case StandardPackageType.WIN_EXE, StandardPackageType.WIN_MSI -> { - if (installDir.isAbsolute()) { - throw ex; + if (type instanceof StandardPackageType stdType) { + switch (stdType) { + case WIN_EXE, WIN_MSI -> { + if (installDir.isAbsolute()) { + throw ex; + } } - } - default -> { - if (!installDir.isAbsolute()) { - throw ex; + default -> { + if (!installDir.isAbsolute()) { + throw ex; + } } } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ToolValidator.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ToolValidator.java index 9440aff3a53..13a9e05e934 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ToolValidator.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ToolValidator.java @@ -33,7 +33,6 @@ import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; -import jdk.internal.util.OperatingSystem; import jdk.jpackage.internal.model.ConfigException; import jdk.jpackage.internal.model.DottedVersion; @@ -46,9 +45,6 @@ final class ToolValidator { ToolValidator(Path toolPath) { this.toolPath = Objects.requireNonNull(toolPath); - if (OperatingSystem.isLinux()) { - setCommandLine("--version"); - } } ToolValidator setCommandLine(String... args) { diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java index d40895a7da6..5789203c3e9 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java @@ -64,14 +64,15 @@ import jdk.jpackage.internal.util.function.ExceptionBox; */ public final class Main { - public record Provider(Supplier bundlingEnvSupplier) implements ToolProvider { + public record Provider(Supplier bundlingEnvSupplier, OperatingSystem os) implements ToolProvider { public Provider { Objects.requireNonNull(bundlingEnvSupplier); + Objects.requireNonNull(os); } public Provider() { - this(DefaultBundlingEnvironmentLoader.INSTANCE); + this(DefaultBundlingEnvironmentLoader.INSTANCE, OperatingSystem.current()); } @Override @@ -81,7 +82,7 @@ public final class Main { @Override public int run(PrintWriter out, PrintWriter err, String... args) { - return Main.run(bundlingEnvSupplier, out, err, args); + return Main.run(os, bundlingEnvSupplier, out, err, args); } @Override @@ -107,25 +108,29 @@ public final class Main { public static void main(String... args) { var out = toPrintWriter(System.out); var err = toPrintWriter(System.err); - System.exit(run(out, err, args)); + System.exit(run(OperatingSystem.current(), DefaultBundlingEnvironmentLoader.INSTANCE, out, err, args)); } - static int run(PrintWriter out, PrintWriter err, String... args) { - return run(DefaultBundlingEnvironmentLoader.INSTANCE, out, err, args); - } - - static int run(Supplier bundlingEnvSupplier, PrintWriter out, PrintWriter err, String... args) { - return Globals.main(() -> { - return runWithGlobals(bundlingEnvSupplier, out, err, args); - }); - } - - private static int runWithGlobals( + static int run( + OperatingSystem os, Supplier bundlingEnvSupplier, PrintWriter out, PrintWriter err, String... args) { + return Globals.main(() -> { + return runWithGlobals(os, bundlingEnvSupplier, out, err, args); + }); + } + + private static int runWithGlobals( + OperatingSystem os, + Supplier bundlingEnvSupplier, + PrintWriter out, + PrintWriter err, + String... args) { + + Objects.requireNonNull(os); Objects.requireNonNull(bundlingEnvSupplier); Objects.requireNonNull(args); for (String arg : args) { @@ -162,7 +167,7 @@ public final class Main { final var bundlingEnv = bundlingEnvSupplier.get(); - final var parseResult = Utils.buildParser(OperatingSystem.current(), bundlingEnv).create().apply(mappedArgs.get()); + final var parseResult = Utils.buildParser(os, bundlingEnv).create().apply(mappedArgs.get()); return runner.run(() -> { final var parsedOptionsBuilder = parseResult.orElseThrow(); @@ -189,7 +194,7 @@ public final class Main { Globals.instance().loggerVerbose(); } - final var optionsProcessor = new OptionsProcessor(parsedOptionsBuilder, bundlingEnv); + final var optionsProcessor = new OptionsProcessor(parsedOptionsBuilder, os, bundlingEnv); final var validationResult = optionsProcessor.validate(); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsAnalyzer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsAnalyzer.java index 6c32a3d1569..fb1dd20df92 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsAnalyzer.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsAnalyzer.java @@ -63,8 +63,8 @@ import jdk.jpackage.internal.model.BundleType; */ final class OptionsAnalyzer { - OptionsAnalyzer(Options cmdline, BundlingEnvironment bundlingEnv) { - this(cmdline, getBundlingOperation(cmdline, OperatingSystem.current(), bundlingEnv), false); + OptionsAnalyzer(Options cmdline, OperatingSystem os, BundlingEnvironment bundlingEnv) { + this(cmdline, getBundlingOperation(cmdline, os, bundlingEnv), false); } OptionsAnalyzer(Options cmdline, StandardBundlingOperation bundlingOperation) { @@ -291,17 +291,17 @@ final class OptionsAnalyzer { return bundlingOperations.getFirst(); } else { // Multiple standard bundling operations produce the `bundleType` bundle type. - // Filter those that belong to the current OS + // Filter those that belong to the specified OS. bundlingOperations = bundlingOperations.stream().filter(op -> { - return op.os().equals(OperatingSystem.current()); + return op.os().equals(os); }).toList(); if (bundlingOperations.isEmpty()) { // jpackage internal error: none of the standard bundling operations produce - // bundles of the `bundleType` on the current OS. + // bundles of the `bundleType` on the specified OS. throw new AssertionError(String.format( "None of the standard bundling operations produce bundles of type [%s] on %s", - bundleType, OperatingSystem.current())); + bundleType, os)); } else if (bundlingOperations.size() == 1) { return bundlingOperations.getFirst(); } else if (StandardBundlingOperation.MACOS_APP_IMAGE.containsAll(bundlingOperations)) { diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java index 3c0eab77f8a..387c36ea416 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java @@ -62,8 +62,9 @@ import jdk.jpackage.internal.util.Result; */ final class OptionsProcessor { - OptionsProcessor(OptionsBuilder optionsBuilder, CliBundlingEnvironment bundlingEnv) { + OptionsProcessor(OptionsBuilder optionsBuilder, OperatingSystem os, CliBundlingEnvironment bundlingEnv) { this.optionsBuilder = Objects.requireNonNull(optionsBuilder); + this.os = Objects.requireNonNull(os); this.bundlingEnv = Objects.requireNonNull(bundlingEnv); } @@ -88,7 +89,7 @@ final class OptionsProcessor { final var untypedOptions = optionsBuilder.create(); // Create command line structure analyzer. - final var analyzerResult = Result.of(() -> new OptionsAnalyzer(untypedOptions, bundlingEnv)); + final var analyzerResult = Result.of(() -> new OptionsAnalyzer(untypedOptions, os, bundlingEnv)); if (analyzerResult.hasErrors()) { // Failed to derive the bundling operation from the command line. allErrors.addAll(analyzerResult.mapErrors().errors()); @@ -419,6 +420,7 @@ final class OptionsProcessor { private final JOptSimpleOptionsBuilder.OptionsBuilder optionsBuilder; + private final OperatingSystem os; private final CliBundlingEnvironment bundlingEnv; private static final OptionValue> ADD_LAUNCHER_INTERNAL = diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java index eca82da99aa..f554fc12ec6 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/StandardOption.java @@ -434,6 +434,12 @@ public final class StandardOption { public static final OptionValue BUNDLING_OPERATION_DESCRIPTOR = OptionValue.create(); + /** + * Debug option telling bundler to exit after the configuration phase is over, + * without running the packaging phase. + */ + public static final OptionValue EXIT_AFTER_CONFIGURATION_PHASE = OptionValue.build().defaultValue(false).create(); + /** * Returns options configuring a launcher. * diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java index 55b13a06620..2dcccc673a9 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AppImageFile.java @@ -41,7 +41,6 @@ import javax.xml.stream.XMLStreamWriter; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; -import jdk.internal.util.OperatingSystem; import jdk.jpackage.internal.util.XmlUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -195,13 +194,16 @@ public record AppImageFile(String mainLauncherName, Optional mainLaunche } private static String getPlatform() { - return PLATFORM_LABELS.get(OperatingSystem.current()); + if (TKit.isLinux()) { + return "linux"; + } else if (TKit.isWindows()) { + return "windows"; + } else if (TKit.isOSX()) { + return "macOS"; + } else { + throw new IllegalStateException(); + } } private static final String FILENAME = ".jpackage.xml"; - - private static final Map PLATFORM_LABELS = Map.of( - OperatingSystem.LINUX, "linux", - OperatingSystem.WINDOWS, "windows", - OperatingSystem.MACOS, "macOS"); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java index 0bbf71fe0cd..4ca4b918355 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package jdk.jpackage.test; import java.nio.file.Path; import java.util.spi.ToolProvider; +import jdk.internal.util.OperatingSystem; public enum JavaTool { JAVA, JAVAC, JPACKAGE, JAR, JLINK, JMOD, JSHELL; @@ -50,7 +51,7 @@ public enum JavaTool { private Path relativePathInJavaHome() { Path path = Path.of("bin", toolName()); - if (TKit.isWindows()) { + if (OperatingSystem.isWindows()) { path = path.getParent().resolve(path.getFileName().toString() + ".exe"); } return path; 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 88d11d75f45..db76309c292 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -77,6 +77,9 @@ import jdk.jpackage.internal.util.function.ThrowingUnaryOperator; public final class TKit { + private static final ScopedValue STATE = ScopedValue.newInstance(); + private static final State DEFAULT_STATE = State.build().initDefaults().mutable(false).create(); + public static final Path TEST_SRC_ROOT = Functional.identity(() -> { Path root = Path.of(System.getProperty("test.src")); @@ -128,6 +131,15 @@ public final class TKit { } } + public static void withOperatingSystem(ThrowingRunnable action, OperatingSystem os) { + Objects.requireNonNull(action); + Objects.requireNonNull(os); + + withState(action, stateBuilder -> { + stateBuilder.os(os); + }); + } + public static void withState(ThrowingRunnable action, Consumer stateBuilderMutator) { Objects.requireNonNull(action); Objects.requireNonNull(stateBuilderMutator); @@ -233,21 +245,25 @@ public final class TKit { } public static boolean isWindows() { - return OperatingSystem.isWindows(); + return TKit.state().os == OperatingSystem.WINDOWS; } public static boolean isOSX() { - return OperatingSystem.isMacOS(); + return TKit.state().os == OperatingSystem.MACOS; } public static boolean isLinux() { - return OperatingSystem.isLinux(); + return TKit.state().os == OperatingSystem.LINUX; } public static boolean isLinuxAPT() { return isLinux() && Files.exists(Path.of("/usr/bin/apt-get")); } + public static boolean isMockingOperatingSystem() { + return TKit.state().os != OperatingSystem.current(); + } + private static String addTimestamp(String msg) { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); Date time = new Date(System.currentTimeMillis()); @@ -1314,6 +1330,7 @@ public final class TKit { public static final class State { private State( + OperatingSystem os, TestInstance currentTest, PrintStream out, PrintStream err, @@ -1323,10 +1340,12 @@ public final class TKit { boolean verboseJPackage, boolean verboseTestSetup) { + Objects.requireNonNull(os); Objects.requireNonNull(out); Objects.requireNonNull(err); Objects.requireNonNull(properties); + this.os = os; this.currentTest = currentTest; this.out = out; this.err = err; @@ -1371,6 +1390,7 @@ public final class TKit { static final class Builder { Builder initDefaults() { + os = null; currentTest = null; out = System.out; err = System.err; @@ -1403,6 +1423,7 @@ public final class TKit { } Builder initFrom(State state) { + os = state.os; currentTest = state.currentTest; out = state.out; err = state.err; @@ -1418,6 +1439,11 @@ public final class TKit { return this; } + Builder os(OperatingSystem v) { + os = v; + return this; + } + Builder currentTest(TestInstance v) { currentTest = v; return this; @@ -1449,6 +1475,7 @@ public final class TKit { State create() { return new State( + Optional.ofNullable(os).orElseGet(OperatingSystem::current), currentTest, out, err, @@ -1459,6 +1486,7 @@ public final class TKit { verboseTestSetup); } + private OperatingSystem os; private TestInstance currentTest; private PrintStream out; private PrintStream err; @@ -1474,6 +1502,7 @@ public final class TKit { } + private OperatingSystem os; private final TestInstance currentTest; private final PrintStream out; private final PrintStream err; @@ -1486,8 +1515,4 @@ public final class TKit { private final boolean verboseJPackage; private final boolean verboseTestSetup; } - - - private static final ScopedValue STATE = ScopedValue.newInstance(); - private static final State DEFAULT_STATE = State.build().initDefaults().mutable(false).create(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/JPackageMockUtils.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/JPackageMockUtils.java index 604bcd0711f..085102390ff 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/JPackageMockUtils.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/stdmock/JPackageMockUtils.java @@ -213,7 +213,7 @@ public final class JPackageMockUtils { var impl = new Main.Provider(runOnce(() -> { return createBundlingEnvironment(os); - })); + }), os); return new ToolProvider() { diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java index 8fdcc96acff..85b15d77052 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/AppImageFileTest.java @@ -108,7 +108,9 @@ public class AppImageFileTest { @Test public void testNoSuchFile() throws IOException { - var ex = assertThrowsExactly(JPackageException.class, () -> AppImageFile.load(DUMMY_LAYOUT.resolveAt(tempFolder))); + var ex = assertThrowsExactly(JPackageException.class, () -> { + AppImageFile.load(DUMMY_LAYOUT.resolveAt(tempFolder), OperatingSystem.current()); + }); Assertions.assertEquals(I18N.format("error.missing-app-image-file", ".jpackage.xml", tempFolder), ex.getMessage()); assertNull(ex.getCause()); } @@ -117,7 +119,9 @@ public class AppImageFileTest { public void testDirectory() throws IOException { Files.createDirectory(AppImageFile.getPathInAppImage(DUMMY_LAYOUT.resolveAt(tempFolder))); - var ex = assertThrowsExactly(JPackageException.class, () -> AppImageFile.load(DUMMY_LAYOUT.resolveAt(tempFolder))); + var ex = assertThrowsExactly(JPackageException.class, () -> { + AppImageFile.load(DUMMY_LAYOUT.resolveAt(tempFolder), OperatingSystem.current()); + }); Assertions.assertEquals(I18N.format("error.reading-app-image-file", ".jpackage.xml", tempFolder), ex.getMessage()); assertNotNull(ex.getCause()); } @@ -131,7 +135,9 @@ public class AppImageFileTest { Files.writeString(appImageFile, ""); try (var out = new FileOutputStream(appImageFile.toFile()); var lock = out.getChannel().lock()) { - var ex = assertThrowsExactly(JPackageException.class, () -> AppImageFile.load(DUMMY_LAYOUT.resolveAt(tempFolder))); + var ex = assertThrowsExactly(JPackageException.class, () -> { + AppImageFile.load(DUMMY_LAYOUT.resolveAt(tempFolder), OperatingSystem.current()); + }); Assertions.assertEquals(I18N.format("error.reading-app-image-file", ".jpackage.xml", tempFolder), ex.getMessage()); assertNotNull(ex.getCause()); } @@ -237,7 +243,7 @@ public class AppImageFileTest { final var copy = toSupplier(() -> { var layout = DUMMY_LAYOUT.resolveAt(dir); new AppImageFile(app).save(layout); - return AppImageFile.load(layout); + return AppImageFile.load(layout, OperatingSystem.current()); }).get(); assertEquals(createExternalApplication(OperatingSystem.current()), copy); @@ -638,7 +644,7 @@ public class AppImageFileTest { private static final ApplicationLayout DUMMY_LAYOUT = ApplicationLayout.build().setAll("").create(); - private final static Map OPTIONS = Stream.of(AppImageFileOptionScope.values()) + private static final Map OPTIONS = Stream.of(AppImageFileOptionScope.values()) .flatMap(AppImageFileOptionScope::options) .collect(toMap(OptionValue::id, OptionValue::getName)); diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java index 1c06d592006..3f933093e97 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java @@ -461,7 +461,11 @@ public class MainTest extends JUnitAdapter { var stdout = new StringWriter(); var stderr = new StringWriter(); - var exitCode = Main.run(new PrintWriter(stdout), new PrintWriter(stderr), args); + var os = OperatingSystem.current(); + var exitCode = Main.run(os, () -> { + CliBundlingEnvironment bundlingEnv = JPackageMockUtils.createBundlingEnvironment(os); + return bundlingEnv; + }, new PrintWriter(stdout), new PrintWriter(stderr), args); return new ExecutionResult(lines(stdout.toString()), lines(stderr.toString()), exitCode); } diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsProcessorTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsProcessorTest.java index 53b726d8f1a..499aab2f24a 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsProcessorTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsProcessorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -664,7 +664,7 @@ public class OptionsProcessorTest { var optionsBuilder = Utils.buildParser(os, bundlingEnv).create().apply(stringArgs).orElseThrow(); - var op = new OptionsProcessor(optionsBuilder, bundlingEnv); + var op = new OptionsProcessor(optionsBuilder, OperatingSystem.current(), bundlingEnv); Collection> errors; if (expectedValidationErrorsOrdered) { diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java index 9976a71ef3f..3381677cb61 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java @@ -105,7 +105,7 @@ public class OptionsValidationFailTest { final var firstErr = errors.stream().findFirst().orElseThrow(); errorReporter.reportError(firstErr); }).map(builder -> { - var result = new OptionsProcessor(builder, bundlingEnv).validate(); + var result = new OptionsProcessor(builder, OperatingSystem.current(), bundlingEnv).validate(); if (result.hasValue()) { return 0; } else { From 7f518deb2c6ac54867a266ce16023183e7ced053 Mon Sep 17 00:00:00 2001 From: Frederic Thevenet Date: Wed, 4 Mar 2026 05:48:30 +0000 Subject: [PATCH 039/170] 8378584: (process) Investigate and fix Alpine errors in Basic.java ProcessBuilder test, and re-enable tests Reviewed-by: stuefe --- test/jdk/java/lang/ProcessBuilder/Basic.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index 7034174f85c..dd97de8fad8 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,6 @@ * @summary Basic tests for Process and Environment Variable code * @modules java.base/java.lang:open * java.base/java.io:open - * @requires !vm.musl * @requires vm.flagless * @library /test/lib * @run main/othervm/native/timeout=360 Basic @@ -46,7 +45,7 @@ * @modules java.base/java.lang:open * java.base/java.io:open * java.base/jdk.internal.misc - * @requires (os.family == "linux" & !vm.musl) + * @requires (os.family == "linux") * @library /test/lib * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=posix_spawn Basic */ From d9e256d3b2bb96ab079ccab51a5d3b32900aa632 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Wed, 4 Mar 2026 06:11:02 +0000 Subject: [PATCH 040/170] 8372245: GTest globalDefinitions.format_specifiers cannot run without VM Reviewed-by: kbarrett, iwalulya --- test/hotspot/gtest/utilities/test_globalDefinitions.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp index 6636efbba8e..b8b65ae8ca8 100644 --- a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp +++ b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,6 @@ */ #include "cppstdlib/type_traits.hpp" -#include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" @@ -220,10 +219,9 @@ TEST(globalDefinitions, array_size) { #define check_format(format, value, expected) \ do { \ - ResourceMark rm; \ stringStream out; \ out.print((format), (value)); \ - const char* result = out.as_string(); \ + const char* result = out.base(); \ EXPECT_STREQ((result), (expected)) << "Failed with" \ << " format '" << (format) << "'" \ << " value '" << (value); \ From 3cd0b99990ae50579e6f99c043beb1ab3f2f5e89 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Wed, 4 Mar 2026 06:13:05 +0000 Subject: [PATCH 041/170] 8372248: GTest istream.coverage depends on istream.basic Reviewed-by: kbarrett, iwalulya --- test/hotspot/gtest/utilities/test_istream.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/test/hotspot/gtest/utilities/test_istream.cpp b/test/hotspot/gtest/utilities/test_istream.cpp index c07450822af..643d8cf8fcf 100644 --- a/test/hotspot/gtest/utilities/test_istream.cpp +++ b/test/hotspot/gtest/utilities/test_istream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -305,16 +305,13 @@ static void istream_test_driver(const bool VERBOSE, } TEST_VM(istream, basic) { - const bool VERBOSE = false; - istream_test_driver(VERBOSE, false, false, false); -} - -TEST_VM(istream, coverage) { - const bool VERBOSE = false; + const bool VERBOSE_TEST = false; + const bool VERBOSE_COVERAGE = false; + istream_test_driver(VERBOSE_TEST, false, false, false); #ifdef ASSERT istream_coverage_mode(0, cases, total, zeroes); if (cases == 0) return; - if (VERBOSE || zeroes != 0) + if (VERBOSE_COVERAGE || zeroes != 0) istream_coverage_mode(-1, cases, total, zeroes); EXPECT_EQ(zeroes, 0) << "zeroes: " << zeroes << "/" << cases; #endif //ASSERT From 39b1e9d839c0f0089565c55accdcab5337839fbf Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Wed, 4 Mar 2026 07:07:00 +0000 Subject: [PATCH 042/170] 8372247: OSX: Semaphore.trywait requires os::Bsd::clock_init Reviewed-by: dholmes, kbarrett --- src/hotspot/os/bsd/semaphore_bsd.cpp | 44 +++++++++++++++++----------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/hotspot/os/bsd/semaphore_bsd.cpp b/src/hotspot/os/bsd/semaphore_bsd.cpp index 827c955677e..c35712ff2da 100644 --- a/src/hotspot/os/bsd/semaphore_bsd.cpp +++ b/src/hotspot/os/bsd/semaphore_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,27 +81,37 @@ bool OSXSemaphore::timedwait(int64_t millis) { // kernel semaphores take a relative timeout mach_timespec_t waitspec; - int secs = millis / MILLIUNITS; - int nsecs = millis_to_nanos(millis % MILLIUNITS); - waitspec.tv_sec = secs; - waitspec.tv_nsec = nsecs; + int64_t starttime; + const bool is_trywait = millis == 0; - int64_t starttime = os::javaTimeNanos(); + if (!is_trywait) { + int secs = millis / MILLIUNITS; + int nsecs = millis_to_nanos(millis % MILLIUNITS); + waitspec.tv_sec = secs; + waitspec.tv_nsec = nsecs; + + starttime = os::javaTimeNanos(); + } else { + waitspec.tv_sec = 0; + waitspec.tv_nsec = 0; + } kr = semaphore_timedwait(_semaphore, waitspec); while (kr == KERN_ABORTED) { - // reduce the timeout and try again - int64_t totalwait = millis_to_nanos(millis); - int64_t current = os::javaTimeNanos(); - int64_t passedtime = current - starttime; + if (!is_trywait) { + // reduce the timeout and try again + int64_t totalwait = millis_to_nanos(millis); + int64_t current = os::javaTimeNanos(); + int64_t passedtime = current - starttime; - if (passedtime >= totalwait) { - waitspec.tv_sec = 0; - waitspec.tv_nsec = 0; - } else { - int64_t waittime = totalwait - (current - starttime); - waitspec.tv_sec = waittime / NANOSECS_PER_SEC; - waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; + if (passedtime >= totalwait) { + waitspec.tv_sec = 0; + waitspec.tv_nsec = 0; + } else { + int64_t waittime = totalwait - (current - starttime); + waitspec.tv_sec = waittime / NANOSECS_PER_SEC; + waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; + } } kr = semaphore_timedwait(_semaphore, waitspec); From 58d2c1d47db8a7defe2c3319cfab943296cf34f1 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 4 Mar 2026 07:17:26 +0000 Subject: [PATCH 043/170] 8371155: Type annotations on local variables are classified after the local var initializer has been type checked Reviewed-by: vromero --- .../sun/tools/javac/code/TypeAnnotations.java | 94 +++++--- .../com/sun/tools/javac/comp/Attr.java | 5 +- .../TypeAnnotationsOnVariables.java | 211 ++++++++++++++++++ 3 files changed, 283 insertions(+), 27 deletions(-) create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsOnVariables.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java index 86319f20c73..8eba79c7480 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -50,6 +50,7 @@ import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Type.ModuleType; +import com.sun.tools.javac.code.Type.UnionClassType; import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.comp.Attr; import com.sun.tools.javac.comp.AttrContext; @@ -61,6 +62,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotatedType; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree; import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCCatch; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; @@ -70,6 +72,7 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCNewArray; import com.sun.tools.javac.tree.JCTree.JCNewClass; +import com.sun.tools.javac.tree.JCTree.JCTry; import com.sun.tools.javac.tree.JCTree.JCTypeApply; import com.sun.tools.javac.tree.JCTree.JCTypeIntersection; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; @@ -111,6 +114,7 @@ public class TypeAnnotations { final Symtab syms; final Annotate annotate; final Attr attr; + final Types types; @SuppressWarnings("this-escape") protected TypeAnnotations(Context context) { @@ -120,6 +124,7 @@ public class TypeAnnotations { syms = Symtab.instance(context); annotate = Annotate.instance(context); attr = Attr.instance(context); + types = Types.instance(context); } /** @@ -132,7 +137,24 @@ public class TypeAnnotations { annotate.afterTypes(() -> { JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); try { - new TypeAnnotationPositions(true).scan(tree); + new TypeAnnotationPositions(null, true).scan(tree); + } finally { + log.useSource(oldSource); + } + }); + } + + public void organizeTypeAnnotationsSignaturesForLocalVarType(final Env env, final JCVariableDecl tree) { + annotate.afterTypes(() -> { + JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); + try { + TypeAnnotationPositions pos = new TypeAnnotationPositions(env.tree, true); + if (env.tree instanceof JCLambda) { + pos.push(env.tree); + } else { + pos.push(env.enclMethod); + } + pos.scan(tree); } finally { log.useSource(oldSource); } @@ -155,7 +177,7 @@ public class TypeAnnotations { * top-level blocks, and method bodies, and should be called from Attr. */ public void organizeTypeAnnotationsBodies(JCClassDecl tree) { - new TypeAnnotationPositions(false).scan(tree); + new TypeAnnotationPositions(null, false).scan(tree); } public enum AnnotationType { DECLARATION, TYPE, NONE, BOTH } @@ -265,9 +287,11 @@ public class TypeAnnotations { private class TypeAnnotationPositions extends TreeScanner { + private final JCTree contextTree; private final boolean sigOnly; - TypeAnnotationPositions(boolean sigOnly) { + TypeAnnotationPositions(JCTree contextTree, boolean sigOnly) { + this.contextTree = contextTree; this.sigOnly = sigOnly; } @@ -455,14 +479,15 @@ public class TypeAnnotations { return type.annotatedType(onlyTypeAnnotations); } else if (type.getKind() == TypeKind.UNION) { // There is a TypeKind, but no TypeTag. + UnionClassType ut = (UnionClassType) type; JCTypeUnion tutree = (JCTypeUnion)typetree; JCExpression fst = tutree.alternatives.get(0); Type res = typeWithAnnotations(fst, fst.type, annotations, onlyTypeAnnotations, pos); fst.type = res; - // TODO: do we want to set res as first element in uct.alternatives? - // UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type; - // Return the un-annotated union-type. - return type; + ListBuffer alternatives = new ListBuffer<>(); + alternatives.add(res); + alternatives.addAll(ut.alternatives_field.tail); + return new UnionClassType((ClassType) ut.getLub(), alternatives.toList()); } else { Type enclTy = type; Element enclEl = type.asElement(); @@ -1237,7 +1262,17 @@ public class TypeAnnotations { } else if (tree.sym == null) { Assert.error("Visiting tree node before memberEnter"); } else if (tree.sym.getKind() == ElementKind.PARAMETER) { - // Parameters are handled in visitMethodDef or visitLambda. + if (sigOnly) { + if (contextTree instanceof JCCatch c && c.param == tree) { + //exception "parameter": + final TypeAnnotationPosition pos = + TypeAnnotationPosition.exceptionParameter(currentLambda, + tree.pos); + separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + } else { + // (real) parameters are handled in visitMethodDef or visitLambda. + } + } } else if (tree.sym.getKind() == ElementKind.FIELD) { if (sigOnly) { TypeAnnotationPosition pos = @@ -1245,27 +1280,36 @@ public class TypeAnnotations { separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); } } else if (tree.sym.getKind() == ElementKind.LOCAL_VARIABLE) { - final TypeAnnotationPosition pos = - TypeAnnotationPosition.localVariable(currentLambda, - tree.pos); - if (!tree.declaredUsingVar()) { - separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + if (sigOnly && !tree.declaredUsingVar()) { + if (contextTree instanceof JCTry t && t.resources.contains(tree)) { + final TypeAnnotationPosition pos = + TypeAnnotationPosition.resourceVariable(currentLambda, + tree.pos); + separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + } else { + final TypeAnnotationPosition pos = + TypeAnnotationPosition.localVariable(currentLambda, + tree.pos); + if (!tree.declaredUsingVar()) { + separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + } + } } } else if (tree.sym.getKind() == ElementKind.BINDING_VARIABLE) { - final TypeAnnotationPosition pos = - TypeAnnotationPosition.localVariable(currentLambda, - tree.pos); - separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + if (sigOnly) { + final TypeAnnotationPosition pos = + TypeAnnotationPosition.localVariable(currentLambda, + tree.pos); + separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + } } else if (tree.sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { - final TypeAnnotationPosition pos = - TypeAnnotationPosition.exceptionParameter(currentLambda, - tree.pos); - separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + if (sigOnly) { + Assert.error("Should not get variable kind: " + tree.sym.getKind()); + } } else if (tree.sym.getKind() == ElementKind.RESOURCE_VARIABLE) { - final TypeAnnotationPosition pos = - TypeAnnotationPosition.resourceVariable(currentLambda, - tree.pos); - separateAnnotationsKinds(tree, tree.vartype, tree.sym.type, tree.sym, pos); + if (sigOnly) { + Assert.error("Should not get variable kind: " + tree.sym.getKind()); + } } else if (tree.sym.getKind() == ElementKind.ENUM_CONSTANT) { // No type annotations can occur here. } else { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 83b684e1225..444530c7266 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1281,6 +1281,7 @@ public class Attr extends JCTree.Visitor { try { annotate.blockAnnotations(); memberEnter.memberEnter(tree, env); + typeAnnotations.organizeTypeAnnotationsSignaturesForLocalVarType(env, tree); } finally { annotate.unblockAnnotations(); } @@ -4226,7 +4227,6 @@ public class Attr extends JCTree.Visitor { } else { type = resultInfo.pt; } - tree.type = tree.var.type = type; BindingSymbol v = new BindingSymbol(tree.var.mods.flags | tree.var.declKind.additionalSymbolFlags, tree.var.name, type, env.info.scope.owner); v.pos = tree.pos; @@ -4244,7 +4244,8 @@ public class Attr extends JCTree.Visitor { annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v); } annotate.flush(); - result = tree.type; + typeAnnotations.organizeTypeAnnotationsSignaturesForLocalVarType(env, tree.var); + result = tree.type = tree.var.type = v.type; if (v.isUnnamedVariable()) { matchBindings = MatchBindingsComputer.EMPTY; } else { diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsOnVariables.java b/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsOnVariables.java new file mode 100644 index 00000000000..2e68e18f8f7 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/TypeAnnotationsOnVariables.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371155 + * @summary Verify type annotations on local-like variables are propagated to + * their types at an appropriate time. + * @library /tools/lib + * @modules + * jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.ToolBox toolbox.JavacTask + * @run main TypeAnnotationsOnVariables + */ + +import com.sun.source.tree.LambdaExpressionTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.TreePathScanner; +import com.sun.source.util.Trees; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.UnionType; +import toolbox.JavacTask; +import toolbox.ToolBox; + +public class TypeAnnotationsOnVariables { + + public static void main(String... args) throws Exception { + new TypeAnnotationsOnVariables().run(); + } + + ToolBox tb = new ToolBox(); + + void run() throws Exception { + typeAnnotationInConstantExpressionFieldInit(Paths.get(".")); + } + + void typeAnnotationInConstantExpressionFieldInit(Path base) throws Exception { + Path src = base.resolve("src"); + Path classes = base.resolve("classes"); + tb.writeJavaFiles(src, + """ + import java.lang.annotation.ElementType; + import java.lang.annotation.Target; + import java.util.function.Supplier; + + class Test { + @Target(ElementType.TYPE_USE) + @interface TypeAnno { } + + @TypeAnno Supplier r_f_i = () -> "r_f_i"; + static @TypeAnno Supplier r_f_s = () -> "r_f_s"; + + { + @TypeAnno Supplier r_init_i = () -> "r_init_i"; + } + + static { + @TypeAnno Supplier r_init_s = () -> "r_init_s"; + } + + void m() { + @TypeAnno Supplier r_m_i = () -> "r_m_i"; + } + + static void g() { + @TypeAnno Supplier r_g_s = () -> "r_g_s"; + } + + void h() { + t_cr(() -> "t_cr"); + } + + void i() { + t_no_cr((@TypeAnno Supplier)() -> "t_no_cr"); + } + + void j() { + t_no_cr((java.io.Serializable & @TypeAnno Supplier)() -> "t_no_cr"); + } + + void k() throws Throwable { + try (@TypeAnno AutoCloseable ac = () -> {}) {} + } + + void l() { + try { + } catch (@TypeAnno Exception e1) {} + } + + void n() { + try { + } catch (@TypeAnno final Exception e2) {} + } + + void o() { + try { + } catch (@TypeAnno IllegalStateException | @TypeAnno NullPointerException | IllegalArgumentException e3) {} + } + + void t_cr(@TypeAnno Supplier r_p) { } + void t_no_cr(@TypeAnno Supplier r_p) { } + } + """); + Files.createDirectories(classes); + List actual = new ArrayList<>(); + new JavacTask(tb) + .options("-d", classes.toString()) + .files(tb.findJavaFiles(src)) + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void finished(TaskEvent e) { + if (e.getKind() != TaskEvent.Kind.ANALYZE) { + return ; + } + Trees trees = Trees.instance(task); + new TreePathScanner() { + @Override + public Void visitVariable(VariableTree node, Void p) { + actual.add(node.getName() + ": " + typeToString(trees.getTypeMirror(getCurrentPath()))); + return super.visitVariable(node, p); + } + @Override + public Void visitLambdaExpression(LambdaExpressionTree node, Void p) { + actual.add(treeToString(node)+ ": " + typeToString(trees.getTypeMirror(getCurrentPath()))); + return super.visitLambdaExpression(node, p); + } + }.scan(e.getCompilationUnit(), null); + } + }); + }) + .run() + .writeAll(); + + List expected = List.of( + "r_f_i: java.util.function.@Test.TypeAnno Supplier", + "()->\"r_f_i\": java.util.function.@Test.TypeAnno Supplier", + "r_f_s: java.util.function.@Test.TypeAnno Supplier", + "()->\"r_f_s\": java.util.function.@Test.TypeAnno Supplier", + "r_init_i: java.util.function.@Test.TypeAnno Supplier", + "()->\"r_init_i\": java.util.function.@Test.TypeAnno Supplier", + "r_init_s: java.util.function.@Test.TypeAnno Supplier", + "()->\"r_init_s\": java.util.function.@Test.TypeAnno Supplier", + "r_m_i: java.util.function.@Test.TypeAnno Supplier", + "()->\"r_m_i\": java.util.function.@Test.TypeAnno Supplier", + "r_g_s: java.util.function.@Test.TypeAnno Supplier", + "()->\"r_g_s\": java.util.function.@Test.TypeAnno Supplier", + "()->\"t_cr\": java.util.function.@Test.TypeAnno Supplier", + "()->\"t_no_cr\": java.util.function.@Test.TypeAnno Supplier", + "()->\"t_no_cr\": java.lang.Object&java.io.Serializable&java.util.function.@Test.TypeAnno Supplier", + "ac: java.lang.@Test.TypeAnno AutoCloseable", + "()->{ }: java.lang.@Test.TypeAnno AutoCloseable", + "e1: java.lang.@Test.TypeAnno Exception", + "e2: java.lang.@Test.TypeAnno Exception", + "e3: java.lang.@Test.TypeAnno IllegalStateException | java.lang.@Test.TypeAnno NullPointerException | java.lang.IllegalArgumentException", + "r_p: java.util.function.@Test.TypeAnno Supplier", + "r_p: java.util.function.@Test.TypeAnno Supplier" + ); + + actual.forEach(System.out::println); + if (!expected.equals(actual)) { + throw new AssertionError("Expected: " + expected + ", but got: " + actual); + } + } + + static String typeToString(TypeMirror type) { + if (type != null && type.getKind() == TypeKind.UNION) { + return ((UnionType) type).getAlternatives().stream().map(t -> typeToString(t)).collect(Collectors.joining(" | ")); + } else { + return String.valueOf(type); + } + } + + static String treeToString(Tree tree) { + if (tree.toString().contains("\n")) { + System.err.println("!!!"); + } + return String.valueOf(tree).replaceAll("\\R", " "); + } +} From f7918df73318892cf2330812669f9c263f513127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Wed, 4 Mar 2026 07:40:44 +0000 Subject: [PATCH 044/170] 8378779: NBody demo test times out with C1 stress testing Reviewed-by: epeter, dfenacci --- .../jtreg/compiler/gallery/TestParticleLife.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/compiler/gallery/TestParticleLife.java b/test/hotspot/jtreg/compiler/gallery/TestParticleLife.java index e0fb6164acf..bb1eea927c7 100644 --- a/test/hotspot/jtreg/compiler/gallery/TestParticleLife.java +++ b/test/hotspot/jtreg/compiler/gallery/TestParticleLife.java @@ -91,7 +91,7 @@ public class TestParticleLife { ParticleLife.State state = new ParticleLife.State(); @Test - @Warmup(100) + @Warmup(75) @IR(counts = {IRNode.REPLICATE_F, "> 0", IRNode.LOAD_VECTOR_F, "> 0", IRNode.SUB_VF, "> 0", @@ -109,7 +109,7 @@ public class TestParticleLife { } @Test - @Warmup(10) + @Warmup(2) @IR(counts = {IRNode.REPLICATE_F, "= 0", IRNode.LOAD_VECTOR_F, "= 0", IRNode.REPLICATE_I, "= 0", @@ -138,7 +138,7 @@ public class TestParticleLife { } @Test - @Warmup(10) + @Warmup(2) @IR(counts = {IRNode.REPLICATE_F, "> 0", IRNode.LOAD_VECTOR_F, "> 0", IRNode.REPLICATE_I, "> 0", @@ -164,7 +164,7 @@ public class TestParticleLife { } @Test - @Warmup(10) + @Warmup(2) @IR(counts = {IRNode.REPLICATE_F, "> 0", IRNode.LOAD_VECTOR_F, "> 0", IRNode.REPLICATE_I, "= 0", // No gather operation @@ -191,7 +191,7 @@ public class TestParticleLife { @Test - @Warmup(10) + @Warmup(2) @IR(counts = {IRNode.REPLICATE_F, "> 0", IRNode.LOAD_VECTOR_F, "> 0", IRNode.REPLICATE_I, "> 0", From 5ab9ddf5e2fa31caa0f62736aff96dd8c12e0177 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 4 Mar 2026 09:32:05 +0000 Subject: [PATCH 045/170] 8378138: G1: Assertion failure from G1CollectedHeap::block_start processing during error reporting Co-authored-by: Yasumasa Suenaga Reviewed-by: ysuenaga, iwalulya --- src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp b/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp index 4f242b7a537..f92e37fee3c 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp @@ -42,6 +42,11 @@ #include "utilities/globalDefinitions.hpp" inline HeapWord* G1HeapRegion::block_start(const void* addr) const { + if (is_young()) { + // We are here because of BlockLocationPrinter. + // Can be invoked in any context, so this region might not be parsable. + return nullptr; + } return block_start(addr, parsable_bottom_acquire()); } @@ -64,6 +69,7 @@ inline HeapWord* G1HeapRegion::advance_to_block_containing_addr(const void* addr inline HeapWord* G1HeapRegion::block_start(const void* addr, HeapWord* const pb) const { assert(addr >= bottom() && addr < top(), "invalid address"); + assert(!is_young(), "Only non-young regions have BOT"); HeapWord* first_block = _bot->block_start_reaching_into_card(addr); return advance_to_block_containing_addr(addr, pb, first_block); } From f26b379b97301aca49dda9cb5dfe9a5472af7140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Wed, 4 Mar 2026 09:49:24 +0000 Subject: [PATCH 046/170] 8378927: H3MultipleConnectionsToSameHost.java#with-continuations intermittent fails Reviewed-by: syan, dfuchs --- .../http3/H3MultipleConnectionsToSameHost.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java b/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java index 67ac821b6f7..f9ba35359bc 100644 --- a/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java +++ b/test/jdk/java/net/httpclient/http3/H3MultipleConnectionsToSameHost.java @@ -30,6 +30,9 @@ * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError + * -Djdk.httpclient.quic.idleTimeout=100000 + * -Djdk.httpclient.keepalive.timeout.h3=100000 + * -Djdk.test.server.quic.idleTimeout=100000 * -Djdk.httpclient.quic.minPtoBackoffTime=60 * -Djdk.httpclient.quic.maxPtoBackoffTime=90 * -Djdk.httpclient.quic.maxPtoBackoff=10 @@ -53,6 +56,9 @@ * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError + * -Djdk.httpclient.quic.idleTimeout=100000 + * -Djdk.httpclient.keepalive.timeout.h3=100000 + * -Djdk.test.server.quic.idleTimeout=100000 * -Djdk.httpclient.quic.minPtoBackoffTime=45 * -Djdk.httpclient.quic.maxPtoBackoffTime=60 * -Djdk.httpclient.quic.maxPtoBackoff=9 @@ -76,9 +82,9 @@ * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError - * -Djdk.httpclient.quic.idleTimeout=120 - * -Djdk.httpclient.keepalive.timeout.h3=120 - * -Djdk.test.server.quic.idleTimeout=90 + * -Djdk.httpclient.quic.idleTimeout=100000 + * -Djdk.httpclient.keepalive.timeout.h3=100000 + * -Djdk.test.server.quic.idleTimeout=100000 * -Djdk.httpclient.quic.minPtoBackoffTime=60 * -Djdk.httpclient.quic.maxPtoBackoffTime=120 * -Djdk.httpclient.quic.maxPtoBackoff=9 @@ -101,9 +107,9 @@ * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.http2.Http2TestServer * @run junit/othervm/timeout=360 -XX:+CrashOnOutOfMemoryError - * -Djdk.httpclient.quic.idleTimeout=120 - * -Djdk.httpclient.keepalive.timeout.h3=120 - * -Djdk.test.server.quic.idleTimeout=90 + * -Djdk.httpclient.quic.idleTimeout=100000 + * -Djdk.httpclient.keepalive.timeout.h3=100000 + * -Djdk.test.server.quic.idleTimeout=100000 * -Djdk.httpclient.quic.minPtoBackoffTime=60 * -Djdk.httpclient.quic.maxPtoBackoffTime=120 * -Djdk.httpclient.quic.maxPtoBackoff=9 From d78a13a7cce07b28668ed88f209f94693f0e607f Mon Sep 17 00:00:00 2001 From: Kerem Kat Date: Wed, 4 Mar 2026 10:39:42 +0000 Subject: [PATCH 047/170] 8366138: Parse::jump_switch_ranges() could cause stack overflow when compiling huge switch statement Reviewed-by: rasbold, dfenacci, mchevalier --- src/hotspot/share/opto/parse2.cpp | 53 +++++++--- .../compiler/c2/TestSwitchStackOverflow.java | 99 +++++++++++++++++++ 2 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestSwitchStackOverflow.java diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index eac2b3e863a..7f41870ccea 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -966,12 +966,28 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, _max_switch_depth = 0; _est_switch_depth = log2i_graceful((hi - lo + 1) - 1) + 1; } + SwitchRange* orig_lo = lo; + SwitchRange* orig_hi = hi; #endif - assert(lo <= hi, "must be a non-empty set of ranges"); - if (lo == hi) { - jump_if_always_fork(lo->dest(), trim_ranges && lo->cnt() == 0); - } else { + // The lower-range processing is done iteratively to avoid O(N) stack depth + // when the profiling-based pivot repeatedly selects mid==lo (JDK-8366138). + // The upper-range processing remains recursive but is only reached for + // balanced splits, bounding its depth to O(log N). + // Termination: every iteration either exits or strictly decreases hi-lo: + // lo == mid && mid < hi, increments lo + // lo < mid <= hi, sets hi = mid - 1. + for (int depth = switch_depth;; depth++) { +#ifndef PRODUCT + _max_switch_depth = MAX2(depth, _max_switch_depth); +#endif + + assert(lo <= hi, "must be a non-empty set of ranges"); + if (lo == hi) { + jump_if_always_fork(lo->dest(), trim_ranges && lo->cnt() == 0); + break; + } + assert(lo->hi() == (lo+1)->lo()-1, "contiguous ranges"); assert(hi->lo() == (hi-1)->hi()+1, "contiguous ranges"); @@ -981,7 +997,12 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, float total_cnt = sum_of_cnts(lo, hi); int nr = hi - lo + 1; - if (UseSwitchProfiling) { + // With total_cnt==0 the profiling pivot degenerates to mid==lo + // (0 >= 0/2), producing a linear chain of If nodes instead of a + // balanced tree. A balanced tree is strictly better here: all paths + // are cold, so a balanced split gives fewer comparisons at runtime + // and avoids pathological memory usage in the optimizer. + if (UseSwitchProfiling && total_cnt > 0) { // Don't keep the binary search tree balanced: pick up mid point // that split frequencies in half. float cnt = 0; @@ -1002,7 +1023,7 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, assert(nr != 2 || mid == hi, "should pick higher of 2"); assert(nr != 3 || mid == hi-1, "should pick middle of 3"); } - + assert(mid != nullptr, "mid must be set"); Node *test_val = _gvn.intcon(mid == lo ? mid->hi() : mid->lo()); @@ -1025,7 +1046,7 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, Node *iffalse = _gvn.transform( new IfFalseNode(iff_lt) ); { PreserveJVMState pjvms(this); set_control(iffalse); - jump_switch_ranges(key_val, mid+1, hi, switch_depth+1); + jump_switch_ranges(key_val, mid+1, hi, depth+1); } set_control(iftrue); } @@ -1043,21 +1064,22 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, Node *iffalse = _gvn.transform( new IfFalseNode(iff_ge) ); { PreserveJVMState pjvms(this); set_control(iftrue); - jump_switch_ranges(key_val, mid == lo ? mid+1 : mid, hi, switch_depth+1); + jump_switch_ranges(key_val, mid == lo ? mid+1 : mid, hi, depth+1); } set_control(iffalse); } } - // in any case, process the lower range + // Process the lower range: iterate instead of recursing. if (mid == lo) { if (mid->is_singleton()) { - jump_switch_ranges(key_val, lo+1, hi, switch_depth+1); + lo++; } else { jump_if_always_fork(lo->dest(), trim_ranges && lo->cnt() == 0); + break; } } else { - jump_switch_ranges(key_val, lo, mid-1, switch_depth+1); + hi = mid - 1; } } @@ -1072,23 +1094,22 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, } #ifndef PRODUCT - _max_switch_depth = MAX2(switch_depth, _max_switch_depth); if (TraceOptoParse && Verbose && WizardMode && switch_depth == 0) { SwitchRange* r; int nsing = 0; - for( r = lo; r <= hi; r++ ) { + for (r = orig_lo; r <= orig_hi; r++) { if( r->is_singleton() ) nsing++; } tty->print(">>> "); _method->print_short_name(); tty->print_cr(" switch decision tree"); tty->print_cr(" %d ranges (%d singletons), max_depth=%d, est_depth=%d", - (int) (hi-lo+1), nsing, _max_switch_depth, _est_switch_depth); + (int) (orig_hi-orig_lo+1), nsing, _max_switch_depth, _est_switch_depth); if (_max_switch_depth > _est_switch_depth) { tty->print_cr("******** BAD SWITCH DEPTH ********"); } tty->print(" "); - for( r = lo; r <= hi; r++ ) { + for (r = orig_lo; r <= orig_hi; r++) { r->print(); } tty->cr(); diff --git a/test/hotspot/jtreg/compiler/c2/TestSwitchStackOverflow.java b/test/hotspot/jtreg/compiler/c2/TestSwitchStackOverflow.java new file mode 100644 index 00000000000..adbfa537aed --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestSwitchStackOverflow.java @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8366138 + * @summary C2: jump_switch_ranges could cause stack overflow when compiling + * huge switch statement with zero-count profiling data. + * @library /test/lib / + * @run main/othervm ${test.main.class} + * @run main/othervm -Xbatch -XX:CompileOnly=Test::test -XX:-DontCompileHugeMethods -XX:CompilerThreadStackSize=512 ${test.main.class} + * @run main/othervm -Xbatch -XX:CompileOnly=Test::test -XX:+DontCompileHugeMethods -XX:CompilerThreadStackSize=512 ${test.main.class} + */ + +package compiler.c2; + +import java.util.stream.Stream; + +import compiler.lib.compile_framework.CompileFramework; +import compiler.lib.template_framework.Template; +import static compiler.lib.template_framework.Template.scope; + +public class TestSwitchStackOverflow { + // Template method exceeds HugeMethodLimit, hence -XX:-DontCompileHugeMethods. + // 5000 cases + CompilerThreadStackSize=512 reliably overflows without the fix. + static final int NUM_CASES = 5000; + + // Generate a class with a large tableswitch method and a main that + // triggers recompilation with zero-count profiling data: + // Phase 1: warm up with default-only path -> C2 compiles + // Phase 2: hit a case -> triggers unstable_if deopt + // Phase 3: recompile with all counts zero (except the default case) + static String generate() { + var caseTemplate = Template.make("i", (Integer i) -> scope( + """ + case #i: + return #i; + """ + )); + var test = Template.make(() -> scope( + """ + public class Test { + static int test(int x) { + switch (x) { + """, + Stream.iterate(0, i -> i + 1) + .limit(NUM_CASES) + .map(i -> caseTemplate.asToken(i)) + .toList(), + """ + default: return -1; + } + } + + public static void main(String[] args) { + for (int i = 0; i < 10_000; i++) { + test(-1); + } + test(42); + for (int i = 0; i < 10_000; i++) { + test(-1); + } + System.out.println("Done"); + } + } + """ + )); + + return test.render(); + } + + public static void main(String[] args) { + CompileFramework comp = new CompileFramework(); + comp.addJavaSourceCode("Test", generate()); + comp.compile(); + comp.invoke("Test", "main", new Object[] { new String[0] }); + } +} From 329e14b0744912293faa7769b22fa348cb1d10aa Mon Sep 17 00:00:00 2001 From: Kerem Kat Date: Wed, 4 Mar 2026 10:56:49 +0000 Subject: [PATCH 048/170] 8375688: C2: Missed Ideal optimization opportunity with VectorMaskToLong and -XX:+StressIncrementalInlining Reviewed-by: qamai, dfenacci --- src/hotspot/share/opto/phaseX.cpp | 10 + .../vectorapi/TestVectorMaskToLongStress.java | 180 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestVectorMaskToLongStress.java diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 3cbbc114778..bc0bed31370 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -2725,6 +2725,16 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ worklist.push(cmp); } } + // VectorMaskToLongNode::Ideal_MaskAll looks through VectorStoreMask + // to fold constant masks. + if (use_op == Op_VectorStoreMask) { + for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { + Node* u = use->fast_out(i2); + if (u->Opcode() == Op_VectorMaskToLong) { + worklist.push(u); + } + } + } // From CastX2PNode::Ideal // CastX2P(AddX(x, y)) diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorMaskToLongStress.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMaskToLongStress.java new file mode 100644 index 00000000000..f9807754539 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorMaskToLongStress.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8375688 + * @key randomness + * @library /test/lib / + * @summary VectorMaskToLong constant folding through VectorStoreMask must work under StressIncrementalInlining + * @modules jdk.incubator.vector + * + * @run driver ${test.main.class} + */ + +package compiler.vectorapi; + +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.*; +import jdk.test.lib.Asserts; + +/** + * Tests that VectorMaskToLongNode::Ideal_MaskAll folds constant masks even + * when StressIncrementalInlining randomizes the IGVN worklist order. + * + * Each test method does {@code VectorMask.fromLong(SPECIES, constant).toLong()} + * and asserts that VectorMaskToLong is folded away entirely (count = 0). + * + * Ideal_MaskAll looks through VectorStoreMask to inspect its input. Without the worklist + * propagation fix in PhaseIterGVN::add_users_of_use_to_worklist (JDK-8375688), VectorMaskToLong + * is not re-visited after VectorStoreMask's input becomes a recognized constant, + * leaving the fold opportunity missed. + * + * IR rules cover three hardware paths: + * - AVX-512/SVE/RVV: masks fold through MaskAll (correctness check only, VectorStoreMask + * is not involved on these platforms) + * - AVX2 without AVX-512: masks go through VectorStoreMask, directly exercising the worklist fix + * - ASIMD without SVE: same VectorStoreMask path, on AArch64 + * + * {@code @Check} methods verify correctness on all platforms, including those where no IR rule applies. + * Float/Double species are excluded because VectorMaskToLong fails to fold their masks + * due to an intervening VectorMaskCast (JDK-8377588). + */ +public class TestVectorMaskToLongStress { + static final VectorSpecies B_SPECIES = ByteVector.SPECIES_MAX; + static final VectorSpecies S_SPECIES = ShortVector.SPECIES_MAX; + static final VectorSpecies I_SPECIES = IntVector.SPECIES_MAX; + static final VectorSpecies L_SPECIES = LongVector.SPECIES_MAX; + + // --- All-ones mask: fromLong(-1).toLong() should fold to a constant --- + + @Test + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureOr = { "avx512", "true", "sve", "true", "rvv", "true" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "avx2", "true", "avx512", "false" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "asimd", "true", "sve", "false" }) + public static long testAllOnesByte() { + return VectorMask.fromLong(B_SPECIES, -1L).toLong(); + } + + @Test + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureOr = { "avx512", "true", "sve", "true", "rvv", "true" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "avx2", "true", "avx512", "false" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "asimd", "true", "sve", "false" }) + public static long testAllOnesShort() { + return VectorMask.fromLong(S_SPECIES, -1L).toLong(); + } + + @Test + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureOr = { "avx512", "true", "sve", "true", "rvv", "true" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "avx2", "true", "avx512", "false" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "asimd", "true", "sve", "false" }) + public static long testAllOnesInt() { + return VectorMask.fromLong(I_SPECIES, -1L).toLong(); + } + + @Test + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureOr = { "avx512", "true", "sve", "true", "rvv", "true" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "avx2", "true", "avx512", "false" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "asimd", "true", "sve", "false" }) + public static long testAllOnesLong() { + return VectorMask.fromLong(L_SPECIES, -1L).toLong(); + } + + // --- All-zeros mask: fromLong(0).toLong() should fold to a constant --- + + @Test + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureOr = { "avx512", "true", "sve", "true", "rvv", "true" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "avx2", "true", "avx512", "false" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "asimd", "true", "sve", "false" }) + public static long testAllZerosByte() { + return VectorMask.fromLong(B_SPECIES, 0L).toLong(); + } + + @Test + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureOr = { "avx512", "true", "sve", "true", "rvv", "true" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "avx2", "true", "avx512", "false" }) + @IR(counts = { IRNode.VECTOR_MASK_TO_LONG, "= 0" }, + applyIfCPUFeatureAnd = { "asimd", "true", "sve", "false" }) + public static long testAllZerosInt() { + return VectorMask.fromLong(I_SPECIES, 0L).toLong(); + } + + // --- Verification --- + + @Check(test = "testAllOnesByte") + public static void checkAllOnesByte(long result) { + Asserts.assertEquals(-1L >>> (64 - B_SPECIES.length()), result); + } + + @Check(test = "testAllOnesShort") + public static void checkAllOnesShort(long result) { + Asserts.assertEquals(-1L >>> (64 - S_SPECIES.length()), result); + } + + @Check(test = "testAllOnesInt") + public static void checkAllOnesInt(long result) { + Asserts.assertEquals(-1L >>> (64 - I_SPECIES.length()), result); + } + + @Check(test = "testAllOnesLong") + public static void checkAllOnesLong(long result) { + Asserts.assertEquals(-1L >>> (64 - L_SPECIES.length()), result); + } + + @Check(test = "testAllZerosByte") + public static void checkAllZerosByte(long result) { + Asserts.assertEquals(0L, result); + } + + @Check(test = "testAllZerosInt") + public static void checkAllZerosInt(long result) { + Asserts.assertEquals(0L, result); + } + + public static void main(String[] args) { + TestFramework testFramework = new TestFramework(); + testFramework.addFlags("--add-modules=jdk.incubator.vector", + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+StressIncrementalInlining", + "-XX:CompileCommand=compileonly,compiler.vectorapi.TestVectorMaskToLongStress::*", + "-XX:VerifyIterativeGVN=1110") + .start(); + } +} From a3b468cec3997c62a2f55302b0338aa0a2bb3055 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 4 Mar 2026 11:12:40 +0000 Subject: [PATCH 049/170] 8379119: G1: Move NoteStartOfMarkHRClosure out of global namespace Reviewed-by: aboldtch, ayang --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 54 +++++++++----------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index ec5649f4fe2..074231a02d4 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -898,9 +898,26 @@ public: }; class G1PreConcurrentStartTask::NoteStartOfMarkTask : public G1AbstractSubTask { + + class NoteStartOfMarkHRClosure : public G1HeapRegionClosure { + G1ConcurrentMark* _cm; + + public: + NoteStartOfMarkHRClosure() : G1HeapRegionClosure(), _cm(G1CollectedHeap::heap()->concurrent_mark()) { } + + bool do_heap_region(G1HeapRegion* r) override { + if (r->is_old_or_humongous() && !r->is_collection_set_candidate() && !r->in_collection_set()) { + _cm->update_top_at_mark_start(r); + } else { + _cm->reset_top_at_mark_start(r); + } + return false; + } + } _region_cl; + G1HeapRegionClaimer _claimer; public: - NoteStartOfMarkTask() : G1AbstractSubTask(G1GCPhaseTimes::NoteStartOfMark), _claimer(0) { } + NoteStartOfMarkTask() : G1AbstractSubTask(G1GCPhaseTimes::NoteStartOfMark), _region_cl(), _claimer(0) { } double worker_cost() const override { // The work done per region is very small, therefore we choose this magic number to cap the number @@ -909,8 +926,13 @@ public: return _claimer.n_regions() / regions_per_thread; } - void set_max_workers(uint max_workers) override; - void do_work(uint worker_id) override; + void set_max_workers(uint max_workers) override { + _claimer.set_n_workers(max_workers); + } + + void do_work(uint worker_id) override { + G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&_region_cl, &_claimer, worker_id); + } }; void G1PreConcurrentStartTask::ResetMarkingStateTask::do_work(uint worker_id) { @@ -918,31 +940,6 @@ void G1PreConcurrentStartTask::ResetMarkingStateTask::do_work(uint worker_id) { _cm->reset(); } -class NoteStartOfMarkHRClosure : public G1HeapRegionClosure { - G1ConcurrentMark* _cm; - -public: - NoteStartOfMarkHRClosure() : G1HeapRegionClosure(), _cm(G1CollectedHeap::heap()->concurrent_mark()) { } - - bool do_heap_region(G1HeapRegion* r) override { - if (r->is_old_or_humongous() && !r->is_collection_set_candidate() && !r->in_collection_set()) { - _cm->update_top_at_mark_start(r); - } else { - _cm->reset_top_at_mark_start(r); - } - return false; - } -}; - -void G1PreConcurrentStartTask::NoteStartOfMarkTask::do_work(uint worker_id) { - NoteStartOfMarkHRClosure start_cl; - G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&start_cl, &_claimer, worker_id); -} - -void G1PreConcurrentStartTask::NoteStartOfMarkTask::set_max_workers(uint max_workers) { - _claimer.set_n_workers(max_workers); -} - G1PreConcurrentStartTask::G1PreConcurrentStartTask(GCCause::Cause cause, G1ConcurrentMark* cm) : G1BatchedTask("Pre Concurrent Start", G1CollectedHeap::heap()->phase_times()) { add_serial_task(new ResetMarkingStateTask(cm)); @@ -962,7 +959,6 @@ void G1ConcurrentMark::pre_concurrent_start(GCCause::Cause cause) { _gc_tracer_cm->set_gc_cause(cause); } - void G1ConcurrentMark::post_concurrent_mark_start() { // Start Concurrent Marking weak-reference discovery. ReferenceProcessor* rp = _g1h->ref_processor_cm(); From ff8b0ac048f6a6f75d1ad738d3354890d76d8128 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Wed, 4 Mar 2026 11:45:09 +0000 Subject: [PATCH 050/170] 8214934: Wrong type annotation offset on casts on expressions Reviewed-by: jlahoda --- .../com/sun/tools/javac/comp/TransTypes.java | 24 ++- .../IncorrectCastOffsetTest.java | 175 ++++++++++++++++++ 2 files changed, 194 insertions(+), 5 deletions(-) create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java 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 862c02ea5f0..1229939c0bf 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 @@ -29,7 +29,6 @@ package com.sun.tools.javac.comp; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.TypeCompound; -import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.TypeVar; import com.sun.tools.javac.jvm.Target; @@ -49,8 +48,6 @@ import static com.sun.tools.javac.code.TypeTag.VOID; import static com.sun.tools.javac.comp.CompileStates.CompileState; import com.sun.tools.javac.tree.JCTree.JCBreak; -import javax.lang.model.type.TypeKind; - /** This pass translates Generic Java to conventional Java. * *

This is NOT part of any supported API. @@ -109,7 +106,9 @@ public class TransTypes extends TreeTranslator { if (!types.isSameType(tree.type, target)) { if (!resolve.isAccessible(env, target.tsym)) resolve.logAccessErrorInternal(env, tree, target); - tree = make.TypeCast(make.Type(target), tree).setType(target); + tree = explicitCastTP != null && types.isSameType(target, explicitCastTP) ? + tree : + make.TypeCast(make.Type(target), tree).setType(target); } make.pos = oldpos; return tree; @@ -440,16 +439,29 @@ public class TransTypes extends TreeTranslator { /** Visitor argument: proto-type. */ private Type pt; + /** we use this type to indicate that "upstream" there is an explicit cast to this type, + * this way we can avoid generating redundant type casts. Redundant casts are not + * innocuous as they can trump user provided ones and affect the offset + * calculation of type annotations applied to the user provided type cast. + */ + private Type explicitCastTP; /** Visitor method: perform a type translation on tree. */ public T translate(T tree, Type pt) { + return translate(tree, pt, pt == explicitCastTP ? explicitCastTP : null); + } + + public T translate(T tree, Type pt, Type castTP) { Type prevPt = this.pt; + Type prevCastPT = this.explicitCastTP; try { this.pt = pt; + this.explicitCastTP = castTP; return translate(tree); } finally { this.pt = prevPt; + this.explicitCastTP = prevCastPT; } } @@ -1037,7 +1049,9 @@ public class TransTypes extends TreeTranslator { tree.clazz = translate(tree.clazz, null); Type originalTarget = tree.type; tree.type = erasure(tree.type); - JCExpression newExpression = translate(tree.expr, tree.type); + JCExpression newExpression = tree.clazz.hasTag(Tag.ANNOTATED_TYPE) ? + translate(tree.expr, tree.type, tree.type) : + translate(tree.expr, tree.type); if (newExpression != tree.expr) { JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST) ? (JCTypeCast) newExpression diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java new file mode 100644 index 00000000000..f679926bcf4 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8214934 + * @summary Wrong type annotation offset on casts on expressions + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.ToolBox toolbox.JavapTask + * @run compile IncorrectCastOffsetTest.java + * @run main IncorrectCastOffsetTest + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import java.util.List; + +import toolbox.JavapTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class IncorrectCastOffsetTest { + @Target(ElementType.TYPE_USE) + @Retention(RetentionPolicy.RUNTIME) + @interface TypeUse {} + + @Target(ElementType.TYPE_USE) + @Retention(RetentionPolicy.RUNTIME) + @interface TypeUse2 {} + + class AnnotatedCast1 { + private static String checkcast(boolean test, Object obj, Object obj2) { + return (@TypeUse String)(test ? obj : obj2); + } + } + + class AnnotatedCast2 { + private static String checkcast(Object obj) { + return (@TypeUse String)(obj); + } + } + + class AnnotatedCast3 { + private static String checkcast(boolean test, Object obj, Object obj2) { + return (@TypeUse @TypeUse2 String)(test ? obj : obj2); + } + } + + class AnnotatedCast4 { + private static String checkcast(Object obj) { + return (@TypeUse String)(@TypeUse2 CharSequence)(obj); + } + } + + ToolBox tb; + + IncorrectCastOffsetTest() { + tb = new ToolBox(); + } + + public static void main(String args[]) { + IncorrectCastOffsetTest incorrectCastOffsetTest = new IncorrectCastOffsetTest(); + incorrectCastOffsetTest.run(); + } + + void run() { + test("IncorrectCastOffsetTest$AnnotatedCast1.class", + /* + * generated code: + * 0: iload_0 + * 1: ifeq 8 + * 4: aload_1 + * 5: goto 9 + * 8: aload_2 + * 9: checkcast #13 // class java/lang/String + * 12: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #35(): CAST, offset=9, type_index=0" + ) + ); + test("IncorrectCastOffsetTest$AnnotatedCast2.class", + /* + * generated code: + * 0: aload_0 + * 1: checkcast #13 // class java/lang/String + * 4: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #31(): CAST, offset=1, type_index=0" + ) + ); + test("IncorrectCastOffsetTest$AnnotatedCast3.class", + /* + * generated code: + * 0: iload_0 + * 1: ifeq 8 + * 4: aload_1 + * 5: goto 9 + * 8: aload_2 + * 9: checkcast #13 // class java/lang/String + * 12: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #35(): CAST, offset=9, type_index=0", + "IncorrectCastOffsetTest$TypeUse", + "1: #36(): CAST, offset=9, type_index=0", + "IncorrectCastOffsetTest$TypeUse2" + ) + ); + test("IncorrectCastOffsetTest$AnnotatedCast4.class", + /* + * generated code: + * 0: aload_0 + * 1: checkcast #13 // class java/lang/CharSequence + * 4: checkcast #15 // class java/lang/String + * 7: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #33(): CAST, offset=4, type_index=0", + "IncorrectCastOffsetTest$TypeUse", + "#34(): CAST, offset=1, type_index=0", + "IncorrectCastOffsetTest$TypeUse2" + ) + ); + } + + void test(String clazz, List expectedOutput) { + Path pathToClass = Paths.get(ToolBox.testClasses, clazz); + String javapOut = new JavapTask(tb) + .options("-v", "-p") + .classes(pathToClass.toString()) + .run() + .getOutput(Task.OutputKind.DIRECT); + + for (String expected : expectedOutput) { + if (!javapOut.contains(expected)) + throw new AssertionError("unexpected output"); + } + } + +} From cb059a6b1b1686b7adcb2e88536060f4f7d47118 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 4 Mar 2026 12:23:31 +0000 Subject: [PATCH 051/170] 8378836: Enable linktime-gc by default on Linux ppc64le Reviewed-by: erikj, jwaters, mdoerr --- make/autoconf/jdk-options.m4 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 87d147d4f07..dafac618c59 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -103,8 +103,12 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], AC_SUBST(ENABLE_HEADLESS_ONLY) # should we linktime gc unused code sections in the JDK build ? - if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = xs390x; then - LINKTIME_GC_DEFAULT=true + if test "x$OPENJDK_TARGET_OS" = "xlinux"; then + if test "x$OPENJDK_TARGET_CPU" = "xs390x" || test "x$OPENJDK_TARGET_CPU" = "xppc64le"; then + LINKTIME_GC_DEFAULT=true + else + LINKTIME_GC_DEFAULT=false + fi else LINKTIME_GC_DEFAULT=false fi From d8d543a5dccf126b23d79750c67424e454f97a7f Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 4 Mar 2026 13:15:27 +0000 Subject: [PATCH 052/170] 8379121: G1: Remove redundant const_cast in g1BlockOffsetTable Reviewed-by: tschatzl, aboldtch --- src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp | 4 ++-- src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index fd70796251d..7f0e5e86cd9 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -73,8 +73,8 @@ void G1BlockOffsetTable::set_offset_array(Atomic* left, Atomic #ifdef ASSERT void G1BlockOffsetTable::check_address(Atomic* addr, const char* msg) const { - Atomic* start_addr = const_cast*>(_offset_base + (uintptr_t(_reserved.start()) >> CardTable::card_shift())); - Atomic* end_addr = const_cast*>(_offset_base + (uintptr_t(_reserved.end()) >> CardTable::card_shift())); + Atomic* start_addr = _offset_base + (uintptr_t(_reserved.start()) >> CardTable::card_shift()); + Atomic* end_addr = _offset_base + (uintptr_t(_reserved.end()) >> CardTable::card_shift()); assert(addr >= start_addr && addr <= end_addr, "%s - offset address: " PTR_FORMAT ", start address: " PTR_FORMAT ", end address: " PTR_FORMAT, msg, (p2i(addr)), (p2i(start_addr)), (p2i(end_addr))); diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index b707e310781..1236d24bb03 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -54,7 +54,7 @@ uint8_t G1BlockOffsetTable::offset_array(Atomic* addr) const { inline Atomic* G1BlockOffsetTable::entry_for_addr(const void* const p) const { assert(_reserved.contains(p), "out of bounds access to block offset table"); - Atomic* result = const_cast*>(&_offset_base[uintptr_t(p) >> CardTable::card_shift()]); + Atomic* result = &_offset_base[uintptr_t(p) >> CardTable::card_shift()]; return result; } From 12af936ae47b8c3be9ff639ef550cb63a94f746e Mon Sep 17 00:00:00 2001 From: Kerem Kat Date: Wed, 4 Mar 2026 13:21:27 +0000 Subject: [PATCH 053/170] 8377986: C2: New method to add specific users to the worklist Reviewed-by: qamai, mchevalier, dfenacci, bmaillard --- src/hotspot/share/opto/phaseX.cpp | 189 +++++++++++------------------- src/hotspot/share/opto/phaseX.hpp | 1 + 2 files changed, 68 insertions(+), 122 deletions(-) diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index bc0bed31370..c77316e7d0b 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -360,6 +360,16 @@ NodeHash::~NodeHash() { } #endif +// Add users of 'n' that match 'predicate' to worklist +template +static void add_users_to_worklist_if(Unique_Node_List& worklist, const Node* n, Predicate predicate) { + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* u = n->fast_out(i); + if (predicate(u)) { + worklist.push(u); + } + } +} //============================================================================= //------------------------------PhaseRemoveUseless----------------------------- @@ -2298,12 +2308,7 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { // A Load that directly follows an InitializeNode is // going away. The Stores that follow are candidates // again to be captured by the InitializeNode. - for (DUIterator_Fast jmax, j = in->fast_outs(jmax); j < jmax; j++) { - Node *n = in->fast_out(j); - if (n->is_Store()) { - _worklist.push(n); - } - } + add_users_to_worklist_if(_worklist, in, [](Node* n) { return n->is_Store(); }); } } // if (in != nullptr && in != C->top()) } // for (uint i = 0; i < dead->req(); i++) @@ -2559,41 +2564,29 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ // If changed LShift inputs, check RShift/URShift users for // "(X << C) >> C" sign-ext and "(X << C) >>> C" zero-ext optimizations. if (use_op == Op_LShiftI || use_op == Op_LShiftL) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_RShiftI || u->Opcode() == Op_RShiftL || - u->Opcode() == Op_URShiftI || u->Opcode() == Op_URShiftL) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { + return u->Opcode() == Op_RShiftI || u->Opcode() == Op_RShiftL || + u->Opcode() == Op_URShiftI || u->Opcode() == Op_URShiftL; + }); } // If changed LShift inputs, check And users for shift and mask (And) operation if (use_op == Op_LShiftI || use_op == Op_LShiftL) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_AndI || u->Opcode() == Op_AndL) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { + return u->Opcode() == Op_AndI || u->Opcode() == Op_AndL; + }); } // If changed AddI/SubI inputs, check CmpU for range check optimization. if (use_op == Op_AddI || use_op == Op_SubI) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->is_Cmp() && (u->Opcode() == Op_CmpU)) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { + return u->Opcode() == Op_CmpU; + }); } // If changed AndI/AndL inputs, check RShift/URShift users for "(x & mask) >> shift" optimization opportunity if (use_op == Op_AndI || use_op == Op_AndL) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_RShiftI || u->Opcode() == Op_RShiftL || - u->Opcode() == Op_URShiftI || u->Opcode() == Op_URShiftL) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { + return u->Opcode() == Op_RShiftI || u->Opcode() == Op_RShiftL || + u->Opcode() == Op_URShiftI || u->Opcode() == Op_URShiftL; + }); } // Check for redundant conversion patterns: // ConvD2L->ConvL2D->ConvD2L @@ -2606,35 +2599,22 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ use_op == Op_ConvI2F || use_op == Op_ConvL2F || use_op == Op_ConvF2I) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if ((use_op == Op_ConvL2D && u->Opcode() == Op_ConvD2L) || - (use_op == Op_ConvI2F && u->Opcode() == Op_ConvF2I) || - (use_op == Op_ConvL2F && u->Opcode() == Op_ConvF2L) || - (use_op == Op_ConvF2I && u->Opcode() == Op_ConvI2F)) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [=](Node* u) { + return (use_op == Op_ConvL2D && u->Opcode() == Op_ConvD2L) || + (use_op == Op_ConvI2F && u->Opcode() == Op_ConvF2I) || + (use_op == Op_ConvL2F && u->Opcode() == Op_ConvF2L) || + (use_op == Op_ConvF2I && u->Opcode() == Op_ConvI2F); + }); } // ConvD2F::Ideal matches ConvD2F(SqrtD(ConvF2D(x))) => SqrtF(x). // Notify ConvD2F users of SqrtD when any input of the SqrtD changes. if (use_op == Op_SqrtD) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_ConvD2F) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { return u->Opcode() == Op_ConvD2F; }); } // ConvF2HF::Ideal matches ConvF2HF(binopF(ConvHF2F(...))) => FP16BinOp(...). // Notify ConvF2HF users of float binary ops when any input changes. if (Float16NodeFactory::is_float32_binary_oper(use_op)) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_ConvF2HF) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { return u->Opcode() == Op_ConvF2HF; }); } // If changed AddP inputs: // - check Stores for loop invariant, and @@ -2642,33 +2622,21 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ // address expression flattening. if (use_op == Op_AddP) { bool offset_changed = n == use->in(AddPNode::Offset); - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->is_Mem()) { - worklist.push(u); - } else if (offset_changed && u->is_AddP() && u->in(AddPNode::Offset)->is_Con()) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [=](Node* u) { + return u->is_Mem() || + (offset_changed && u->is_AddP() && u->in(AddPNode::Offset)->is_Con()); + }); } // Check for "abs(0-x)" into "abs(x)" conversion if (use->is_Sub()) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_AbsD || u->Opcode() == Op_AbsF || - u->Opcode() == Op_AbsL || u->Opcode() == Op_AbsI) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { + return u->Opcode() == Op_AbsD || u->Opcode() == Op_AbsF || + u->Opcode() == Op_AbsL || u->Opcode() == Op_AbsI; + }); } // Check for Max/Min(A, Max/Min(B, C)) where A == B or A == C if (use->is_MinMax()) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->is_MinMax()) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { return u->is_MinMax(); }); } auto enqueue_init_mem_projs = [&](ProjNode* proj) { add_users_to_worklist0(proj, worklist); @@ -2707,12 +2675,9 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ if (u->Opcode() == Op_LoadP && ut->isa_instptr()) { if (has_load_barrier_nodes) { // Search for load barriers behind the load - for (DUIterator_Fast i3max, i3 = u->fast_outs(i3max); i3 < i3max; i3++) { - Node* b = u->fast_out(i3); - if (bs->is_gc_barrier_node(b)) { - worklist.push(b); - } - } + add_users_to_worklist_if(worklist, u, [&](Node* b) { + return bs->is_gc_barrier_node(b); + }); } worklist.push(u); } @@ -2728,24 +2693,14 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ // VectorMaskToLongNode::Ideal_MaskAll looks through VectorStoreMask // to fold constant masks. if (use_op == Op_VectorStoreMask) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_VectorMaskToLong) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { return u->Opcode() == Op_VectorMaskToLong; }); } // From CastX2PNode::Ideal // CastX2P(AddX(x, y)) // CastX2P(SubX(x, y)) if (use->Opcode() == Op_AddX || use->Opcode() == Op_SubX) { - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == Op_CastX2P) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [](Node* u) { return u->Opcode() == Op_CastX2P; }); } /* AndNode has a special handling when one of the operands is a LShiftNode: @@ -2780,12 +2735,7 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_ // e.g., (x - y) + y -> x; x + (y - x) -> y. if (use_op == Op_SubI || use_op == Op_SubL) { const int add_op = (use_op == Op_SubI) ? Op_AddI : Op_AddL; - for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) { - Node* u = use->fast_out(i2); - if (u->Opcode() == add_op) { - worklist.push(u); - } - } + add_users_to_worklist_if(worklist, use, [=](Node* u) { return u->Opcode() == add_op; }); } } @@ -2970,6 +2920,10 @@ void PhaseCCP::dump_type_and_node(const Node* n, const Type* t) { } #endif +bool PhaseCCP::not_bottom_type(Node* n) const { + return n->bottom_type() != type(n); +} + // We need to propagate the type change of 'n' to all its uses. Depending on the kind of node, additional nodes // (grandchildren or even further down) need to be revisited as their types could also be improved as a result // of the new type of 'n'. Push these nodes to the worklist. @@ -2982,7 +2936,7 @@ void PhaseCCP::push_child_nodes_to_worklist(Unique_Node_List& worklist, Node* n) } void PhaseCCP::push_if_not_bottom_type(Unique_Node_List& worklist, Node* n) const { - if (n->bottom_type() != type(n)) { + if (not_bottom_type(n)) { worklist.push(n); } } @@ -3005,9 +2959,9 @@ void PhaseCCP::push_more_uses(Unique_Node_List& worklist, Node* parent, const No // We must recheck Phis too if use is a Region. void PhaseCCP::push_phis(Unique_Node_List& worklist, const Node* use) const { if (use->is_Region()) { - for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { - push_if_not_bottom_type(worklist, use->fast_out(i)); - } + add_users_to_worklist_if(worklist, use, [&](Node* u) { + return not_bottom_type(u); + }); } } @@ -3034,14 +2988,11 @@ void PhaseCCP::push_catch(Unique_Node_List& worklist, const Node* use) { void PhaseCCP::push_cmpu(Unique_Node_List& worklist, const Node* use) const { uint use_op = use->Opcode(); if (use_op == Op_AddI || use_op == Op_SubI) { - for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { - Node* cmpu = use->fast_out(i); - const uint cmpu_opcode = cmpu->Opcode(); - if (cmpu_opcode == Op_CmpU || cmpu_opcode == Op_CmpU3) { - // Got a CmpU or CmpU3 which might need the new type information from node n. - push_if_not_bottom_type(worklist, cmpu); - } - } + // Got a CmpU or CmpU3 which might need the new type information from node n. + add_users_to_worklist_if(worklist, use, [&](Node* u) { + uint op = u->Opcode(); + return (op == Op_CmpU || op == Op_CmpU3) && not_bottom_type(u); + }); } } @@ -3130,12 +3081,9 @@ void PhaseCCP::push_loadp(Unique_Node_List& worklist, const Node* use) const { } void PhaseCCP::push_load_barrier(Unique_Node_List& worklist, const BarrierSetC2* barrier_set, const Node* use) { - for (DUIterator_Fast imax, i = use->fast_outs(imax); i < imax; i++) { - Node* barrier_node = use->fast_out(i); - if (barrier_set->is_gc_barrier_node(barrier_node)) { - worklist.push(barrier_node); - } - } + add_users_to_worklist_if(worklist, use, [&](Node* u) { + return barrier_set->is_gc_barrier_node(u); + }); } // AndI/L::Value() optimizes patterns similar to (v << 2) & 3, or CON & 3 to zero if they are bitwise disjoint. @@ -3171,12 +3119,9 @@ void PhaseCCP::push_and(Unique_Node_List& worklist, const Node* parent, const No void PhaseCCP::push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const { if (use->Opcode() == Op_CmpI && use->in(2) == parent) { Node* other_cmp_input = use->in(1); - for (DUIterator_Fast imax, i = other_cmp_input->fast_outs(imax); i < imax; i++) { - Node* cast_ii = other_cmp_input->fast_out(i); - if (cast_ii->is_CastII()) { - push_if_not_bottom_type(worklist, cast_ii); - } - } + add_users_to_worklist_if(worklist, other_cmp_input, [&](Node* u) { + return u->is_CastII() && not_bottom_type(u); + }); } } diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index cd38f37ccf5..94890c250c4 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -652,6 +652,7 @@ class PhaseCCP : public PhaseIterGVN { Node* fetch_next_node(Unique_Node_List& worklist); static void dump_type_and_node(const Node* n, const Type* t) PRODUCT_RETURN; + bool not_bottom_type(Node* n) const; void push_child_nodes_to_worklist(Unique_Node_List& worklist, Node* n) const; void push_if_not_bottom_type(Unique_Node_List& worklist, Node* n) const; void push_more_uses(Unique_Node_List& worklist, Node* parent, const Node* use) const; From 7c8f66c831e96d7ba6ffa0042130c556290761fc Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 4 Mar 2026 13:22:24 +0000 Subject: [PATCH 054/170] 8379041: Crash in ResolvedFieldEntry::assert_is_valid(): invalid put bytecode 0 Reviewed-by: matsaave, dholmes --- src/hotspot/share/oops/resolvedFieldEntry.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/oops/resolvedFieldEntry.cpp b/src/hotspot/share/oops/resolvedFieldEntry.cpp index 49e9115ca9a..122ecf092d8 100644 --- a/src/hotspot/share/oops/resolvedFieldEntry.cpp +++ b/src/hotspot/share/oops/resolvedFieldEntry.cpp @@ -77,10 +77,13 @@ void ResolvedFieldEntry::assert_is_valid() const { "field offset out of range %d >= %d", field_offset(), instanceOopDesc::base_offset_in_bytes()); assert(as_BasicType((TosState)tos_state()) != T_ILLEGAL, "tos_state is ILLEGAL"); assert(_flags < (1 << (max_flag_shift + 1)), "flags are too large %d", _flags); - assert((get_code() == 0 || get_code() == Bytecodes::_getstatic || get_code() == Bytecodes::_getfield), - "invalid get bytecode %d", get_code()); - assert((put_code() == 0 || put_code() == Bytecodes::_putstatic || put_code() == Bytecodes::_putfield), - "invalid put bytecode %d", put_code()); + + // Read each bytecode once. + volatile Bytecodes::Code g = (Bytecodes::Code)get_code(); + assert(g == 0 || g == Bytecodes::_getstatic || g == Bytecodes::_getfield, "invalid get bytecode %d", g); + + volatile Bytecodes::Code p = (Bytecodes::Code)put_code(); + assert(p == 0 || p == Bytecodes::_putstatic || p == Bytecodes::_putfield, "invalid put bytecode %d", p); } #endif From eb50630d9893970ed58034e878dfdc0ecf0961da Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 4 Mar 2026 13:57:22 +0000 Subject: [PATCH 055/170] 8379013: Remove some unused code in generateOopMap.cpp Reviewed-by: matsaave, dholmes --- src/hotspot/share/interpreter/oopMapCache.cpp | 28 +---------- src/hotspot/share/oops/generateOopMap.cpp | 50 ++----------------- src/hotspot/share/oops/generateOopMap.hpp | 41 ++------------- 3 files changed, 8 insertions(+), 111 deletions(-) diff --git a/src/hotspot/share/interpreter/oopMapCache.cpp b/src/hotspot/share/interpreter/oopMapCache.cpp index 29d6825d3e5..3769a473e3d 100644 --- a/src/hotspot/share/interpreter/oopMapCache.cpp +++ b/src/hotspot/share/interpreter/oopMapCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,15 +78,10 @@ class OopMapForCacheEntry: public GenerateOopMap { int _stack_top; virtual bool report_results() const { return false; } - virtual bool possible_gc_point (BytecodeStream *bcs); - virtual void fill_stackmap_prolog (int nof_gc_points); - virtual void fill_stackmap_epilog (); virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top); - virtual void fill_init_vars (GrowableArray *init_vars); - public: OopMapForCacheEntry(const methodHandle& method, int bci, OopMapCacheEntry *entry); @@ -119,27 +114,6 @@ bool OopMapForCacheEntry::compute_map(Thread* current) { return true; } - -bool OopMapForCacheEntry::possible_gc_point(BytecodeStream *bcs) { - return false; // We are not reporting any result. We call result_for_basicblock directly -} - - -void OopMapForCacheEntry::fill_stackmap_prolog(int nof_gc_points) { - // Do nothing -} - - -void OopMapForCacheEntry::fill_stackmap_epilog() { - // Do nothing -} - - -void OopMapForCacheEntry::fill_init_vars(GrowableArray *init_vars) { - // Do nothing -} - - void OopMapForCacheEntry::fill_stackmap_for_opcodes(BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, diff --git a/src/hotspot/share/oops/generateOopMap.cpp b/src/hotspot/share/oops/generateOopMap.cpp index 97d8bf3d526..db1e8b4548b 100644 --- a/src/hotspot/share/oops/generateOopMap.cpp +++ b/src/hotspot/share/oops/generateOopMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -391,7 +391,6 @@ void CellTypeState::print(outputStream *os) { // void GenerateOopMap::initialize_bb() { - _gc_points = 0; _bb_count = 0; _bb_hdr_bits.reinitialize(method()->code_size()); } @@ -409,7 +408,7 @@ void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) { } -void GenerateOopMap::mark_bbheaders_and_count_gc_points() { +void GenerateOopMap::mark_bbheaders() { initialize_bb(); bool fellThrough = false; // False to get first BB marked. @@ -445,9 +444,6 @@ void GenerateOopMap::mark_bbheaders_and_count_gc_points() { default: break; } - - if (possible_gc_point(&bcs)) - _gc_points++; } } @@ -1051,9 +1047,6 @@ void GenerateOopMap::setup_method_entry_state() { // Initialize CellState type of arguments methodsig_to_effect(method()->signature(), method()->is_static(), vars()); - // If some references must be pre-assigned to null, then set that up - initialize_vars(); - // This is the start state merge_state_into_bb(&_basic_blocks[0]); @@ -1077,27 +1070,6 @@ void GenerateOopMap::update_basic_blocks(int bci, int delta, } } -// -// Initvars handling -// - -void GenerateOopMap::initialize_vars() { - for (int k = 0; k < _init_vars->length(); k++) - _state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k); -} - -void GenerateOopMap::add_to_ref_init_set(int localNo) { - - if (TraceNewOopMapGeneration) - tty->print_cr("Added init vars: %d", localNo); - - // Is it already in the set? - if (_init_vars->contains(localNo) ) - return; - - _init_vars->append(localNo); -} - // // Interpreration code // @@ -1672,7 +1644,6 @@ void GenerateOopMap::ppload(CellTypeState *out, int loc_no) { if (vcts.can_be_uninit()) { // It is a ref-uninit conflict (at least). If there are other // problems, we'll get them in the next round - add_to_ref_init_set(loc_no); vcts = out1; } else { // It wasn't a ref-uninit conflict. So must be a @@ -2065,7 +2036,6 @@ GenerateOopMap::GenerateOopMap(const methodHandle& method) { // We have to initialize all variables here, that can be queried directly _method = method; _max_locals=0; - _init_vars = nullptr; #ifndef PRODUCT // If we are doing a detailed trace, include the regular trace information. @@ -2095,7 +2065,6 @@ bool GenerateOopMap::compute_map(Thread* current) { _max_stack = method()->max_stack(); _has_exceptions = (method()->has_exception_handler()); _nof_refval_conflicts = 0; - _init_vars = new GrowableArray(5); // There are seldom more than 5 init_vars _report_result = false; _report_result_for_send = false; _new_var_map = nullptr; @@ -2119,8 +2088,6 @@ bool GenerateOopMap::compute_map(Thread* current) { // if no code - do nothing // compiler needs info if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) { - fill_stackmap_prolog(0); - fill_stackmap_epilog(); return true; } // Step 1: Compute all jump targets and their return value @@ -2129,7 +2096,7 @@ bool GenerateOopMap::compute_map(Thread* current) { // Step 2: Find all basic blocks and count GC points if (!_got_error) - mark_bbheaders_and_count_gc_points(); + mark_bbheaders(); // Step 3: Calculate stack maps if (!_got_error) @@ -2186,9 +2153,6 @@ void GenerateOopMap::report_result() { // We now want to report the result of the parse _report_result = true; - // Prolog code - fill_stackmap_prolog(_gc_points); - // Mark everything changed, then do one interpretation pass. for (int i = 0; i<_bb_count; i++) { if (_basic_blocks[i].is_reachable()) { @@ -2197,14 +2161,6 @@ void GenerateOopMap::report_result() { } } - // Note: Since we are skipping dead-code when we are reporting results, then - // the no. of encountered gc-points might be fewer than the previously number - // we have counted. (dead-code is a pain - it should be removed before we get here) - fill_stackmap_epilog(); - - // Report initvars - fill_init_vars(_init_vars); - _report_result = false; } diff --git a/src/hotspot/share/oops/generateOopMap.hpp b/src/hotspot/share/oops/generateOopMap.hpp index 0da3779d463..7c445887ee7 100644 --- a/src/hotspot/share/oops/generateOopMap.hpp +++ b/src/hotspot/share/oops/generateOopMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -348,17 +348,15 @@ class GenerateOopMap { // Basicblock info BasicBlock * _basic_blocks; // Array of basicblock info - int _gc_points; int _bb_count; ResourceBitMap _bb_hdr_bits; // Basicblocks methods void initialize_bb (); - void mark_bbheaders_and_count_gc_points(); + void mark_bbheaders(); bool is_bb_header (int bci) const { return _bb_hdr_bits.at(bci); } - int gc_points () const { return _gc_points; } int bb_count () const { return _bb_count; } void set_bbmark_bit (int bci); BasicBlock * get_basic_block_at (int bci) const; @@ -419,12 +417,6 @@ class GenerateOopMap { void report_result (); - // Initvars - GrowableArray * _init_vars; - - void initialize_vars (); - void add_to_ref_init_set (int localNo); - // Conflicts rewrite logic bool _conflict; // True, if a conflict occurred during interpretation int _nof_refval_conflicts; // No. of conflicts that require rewrites @@ -450,7 +442,7 @@ class GenerateOopMap { int binsToHold (int no) { return ((no+(BitsPerWord-1))/BitsPerWord); } char *state_vec_to_string (CellTypeState* vec, int len); - // Helper method. Can be used in subclasses to fx. calculate gc_points. If the current instruction + // Helper method. If the current instruction // is a control transfer, then calls the jmpFct all possible destinations. void ret_jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int varNo,int *data); bool jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int *data); @@ -480,14 +472,7 @@ class GenerateOopMap { bool monitor_safe() { return _monitor_safe; } // Specialization methods. Intended use: - // - possible_gc_point must return true for every bci for which the stackmaps must be returned - // - fill_stackmap_prolog is called just before the result is reported. The arguments tells the estimated - // number of gc points // - fill_stackmap_for_opcodes is called once for each bytecode index in order (0...code_length-1) - // - fill_stackmap_epilog is called after all results has been reported. Note: Since the algorithm does not report - // stackmaps for deadcode, fewer gc_points might have been encountered than assumed during the epilog. It is the - // responsibility of the subclass to count the correct number. - // - fill_init_vars are called once with the result of the init_vars computation // // All these methods are used during a call to: compute_map. Note: Non of the return results are valid // after compute_map returns, since all values are allocated as resource objects. @@ -495,15 +480,10 @@ class GenerateOopMap { // All virtual method must be implemented in subclasses virtual bool allow_rewrites () const { return false; } virtual bool report_results () const { return true; } - virtual bool report_init_vars () const { return true; } - virtual bool possible_gc_point (BytecodeStream *bcs) { ShouldNotReachHere(); return false; } - virtual void fill_stackmap_prolog (int nof_gc_points) { ShouldNotReachHere(); } - virtual void fill_stackmap_epilog () { ShouldNotReachHere(); } virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stackTop) { ShouldNotReachHere(); } - virtual void fill_init_vars (GrowableArray *init_vars) { ShouldNotReachHere();; } }; // @@ -513,19 +493,12 @@ class GenerateOopMap { class ResolveOopMapConflicts: public GenerateOopMap { private: - bool _must_clear_locals; - virtual bool report_results() const { return false; } - virtual bool report_init_vars() const { return true; } virtual bool allow_rewrites() const { return true; } - virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } - virtual void fill_stackmap_prolog (int nof_gc_points) {} - virtual void fill_stackmap_epilog () {} virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top) {} - virtual void fill_init_vars (GrowableArray *init_vars) { _must_clear_locals = init_vars->length() > 0; } #ifndef PRODUCT // Statistics @@ -535,10 +508,9 @@ class ResolveOopMapConflicts: public GenerateOopMap { #endif public: - ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { _must_clear_locals = false; }; + ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { } methodHandle do_potential_rewrite(TRAPS); - bool must_clear_locals() const { return _must_clear_locals; } }; @@ -549,16 +521,11 @@ class GeneratePairingInfo: public GenerateOopMap { private: virtual bool report_results() const { return false; } - virtual bool report_init_vars() const { return false; } virtual bool allow_rewrites() const { return false; } - virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } - virtual void fill_stackmap_prolog (int nof_gc_points) {} - virtual void fill_stackmap_epilog () {} virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top) {} - virtual void fill_init_vars (GrowableArray *init_vars) {} public: GeneratePairingInfo(const methodHandle& method) : GenerateOopMap(method) {}; From 3531c78dea58f1c33752685bd1a876162ec03825 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Wed, 4 Mar 2026 14:30:31 +0000 Subject: [PATCH 056/170] 8379196: delta apply fix for JDK-8214934 Reviewed-by: jlahoda --- .../com/sun/tools/javac/comp/TransTypes.java | 24 +-- .../IncorrectCastOffsetTest.java | 175 ------------------ 2 files changed, 5 insertions(+), 194 deletions(-) delete mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java 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 1229939c0bf..862c02ea5f0 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 @@ -29,6 +29,7 @@ package com.sun.tools.javac.comp; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.TypeCompound; +import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.TypeVar; import com.sun.tools.javac.jvm.Target; @@ -48,6 +49,8 @@ import static com.sun.tools.javac.code.TypeTag.VOID; import static com.sun.tools.javac.comp.CompileStates.CompileState; import com.sun.tools.javac.tree.JCTree.JCBreak; +import javax.lang.model.type.TypeKind; + /** This pass translates Generic Java to conventional Java. * *

This is NOT part of any supported API. @@ -106,9 +109,7 @@ public class TransTypes extends TreeTranslator { if (!types.isSameType(tree.type, target)) { if (!resolve.isAccessible(env, target.tsym)) resolve.logAccessErrorInternal(env, tree, target); - tree = explicitCastTP != null && types.isSameType(target, explicitCastTP) ? - tree : - make.TypeCast(make.Type(target), tree).setType(target); + tree = make.TypeCast(make.Type(target), tree).setType(target); } make.pos = oldpos; return tree; @@ -439,29 +440,16 @@ public class TransTypes extends TreeTranslator { /** Visitor argument: proto-type. */ private Type pt; - /** we use this type to indicate that "upstream" there is an explicit cast to this type, - * this way we can avoid generating redundant type casts. Redundant casts are not - * innocuous as they can trump user provided ones and affect the offset - * calculation of type annotations applied to the user provided type cast. - */ - private Type explicitCastTP; /** Visitor method: perform a type translation on tree. */ public T translate(T tree, Type pt) { - return translate(tree, pt, pt == explicitCastTP ? explicitCastTP : null); - } - - public T translate(T tree, Type pt, Type castTP) { Type prevPt = this.pt; - Type prevCastPT = this.explicitCastTP; try { this.pt = pt; - this.explicitCastTP = castTP; return translate(tree); } finally { this.pt = prevPt; - this.explicitCastTP = prevCastPT; } } @@ -1049,9 +1037,7 @@ public class TransTypes extends TreeTranslator { tree.clazz = translate(tree.clazz, null); Type originalTarget = tree.type; tree.type = erasure(tree.type); - JCExpression newExpression = tree.clazz.hasTag(Tag.ANNOTATED_TYPE) ? - translate(tree.expr, tree.type, tree.type) : - translate(tree.expr, tree.type); + JCExpression newExpression = translate(tree.expr, tree.type); if (newExpression != tree.expr) { JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST) ? (JCTypeCast) newExpression diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java deleted file mode 100644 index f679926bcf4..00000000000 --- a/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8214934 - * @summary Wrong type annotation offset on casts on expressions - * @library /tools/lib - * @modules jdk.compiler/com.sun.tools.javac.api - * jdk.compiler/com.sun.tools.javac.main - * jdk.jdeps/com.sun.tools.javap - * @build toolbox.ToolBox toolbox.JavapTask - * @run compile IncorrectCastOffsetTest.java - * @run main IncorrectCastOffsetTest - */ - -import java.lang.annotation.ElementType; -import java.lang.annotation.Target; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import java.util.List; - -import toolbox.JavapTask; -import toolbox.Task; -import toolbox.ToolBox; - -public class IncorrectCastOffsetTest { - @Target(ElementType.TYPE_USE) - @Retention(RetentionPolicy.RUNTIME) - @interface TypeUse {} - - @Target(ElementType.TYPE_USE) - @Retention(RetentionPolicy.RUNTIME) - @interface TypeUse2 {} - - class AnnotatedCast1 { - private static String checkcast(boolean test, Object obj, Object obj2) { - return (@TypeUse String)(test ? obj : obj2); - } - } - - class AnnotatedCast2 { - private static String checkcast(Object obj) { - return (@TypeUse String)(obj); - } - } - - class AnnotatedCast3 { - private static String checkcast(boolean test, Object obj, Object obj2) { - return (@TypeUse @TypeUse2 String)(test ? obj : obj2); - } - } - - class AnnotatedCast4 { - private static String checkcast(Object obj) { - return (@TypeUse String)(@TypeUse2 CharSequence)(obj); - } - } - - ToolBox tb; - - IncorrectCastOffsetTest() { - tb = new ToolBox(); - } - - public static void main(String args[]) { - IncorrectCastOffsetTest incorrectCastOffsetTest = new IncorrectCastOffsetTest(); - incorrectCastOffsetTest.run(); - } - - void run() { - test("IncorrectCastOffsetTest$AnnotatedCast1.class", - /* - * generated code: - * 0: iload_0 - * 1: ifeq 8 - * 4: aload_1 - * 5: goto 9 - * 8: aload_2 - * 9: checkcast #13 // class java/lang/String - * 12: areturn - */ - List.of( - "RuntimeVisibleTypeAnnotations:", - "0: #35(): CAST, offset=9, type_index=0" - ) - ); - test("IncorrectCastOffsetTest$AnnotatedCast2.class", - /* - * generated code: - * 0: aload_0 - * 1: checkcast #13 // class java/lang/String - * 4: areturn - */ - List.of( - "RuntimeVisibleTypeAnnotations:", - "0: #31(): CAST, offset=1, type_index=0" - ) - ); - test("IncorrectCastOffsetTest$AnnotatedCast3.class", - /* - * generated code: - * 0: iload_0 - * 1: ifeq 8 - * 4: aload_1 - * 5: goto 9 - * 8: aload_2 - * 9: checkcast #13 // class java/lang/String - * 12: areturn - */ - List.of( - "RuntimeVisibleTypeAnnotations:", - "0: #35(): CAST, offset=9, type_index=0", - "IncorrectCastOffsetTest$TypeUse", - "1: #36(): CAST, offset=9, type_index=0", - "IncorrectCastOffsetTest$TypeUse2" - ) - ); - test("IncorrectCastOffsetTest$AnnotatedCast4.class", - /* - * generated code: - * 0: aload_0 - * 1: checkcast #13 // class java/lang/CharSequence - * 4: checkcast #15 // class java/lang/String - * 7: areturn - */ - List.of( - "RuntimeVisibleTypeAnnotations:", - "0: #33(): CAST, offset=4, type_index=0", - "IncorrectCastOffsetTest$TypeUse", - "#34(): CAST, offset=1, type_index=0", - "IncorrectCastOffsetTest$TypeUse2" - ) - ); - } - - void test(String clazz, List expectedOutput) { - Path pathToClass = Paths.get(ToolBox.testClasses, clazz); - String javapOut = new JavapTask(tb) - .options("-v", "-p") - .classes(pathToClass.toString()) - .run() - .getOutput(Task.OutputKind.DIRECT); - - for (String expected : expectedOutput) { - if (!javapOut.contains(expected)) - throw new AssertionError("unexpected output"); - } - } - -} From 4d2c537189cba77d3bbfab36ca3e1c3ceb7c603f Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 4 Mar 2026 17:16:32 +0000 Subject: [PATCH 057/170] 8378992: Case folding cache should not look up code point U+0000 Reviewed-by: sherman, rriggs --- .../classes/jdk/internal/lang/CaseFolding.java.template | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template b/src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template index 24a183c8da0..24f48151f21 100644 --- a/src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template +++ b/src/java.base/share/classes/jdk/internal/lang/CaseFolding.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,6 +188,12 @@ public final class CaseFolding { } private static long getDefined(int cp) { + // Exclude code point U+0000, which is guaranteed to have no + // case-folding mapping. + if (cp == 0) { + return -1; + } + var hashes = CASE_FOLDING_HASHES; var length = CASE_FOLDING_CPS.length; // hashed based on total defined. var hash = cp % length; From 8b91537f109b22333c6008ba64cada9711534cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Wed, 4 Mar 2026 17:17:31 +0000 Subject: [PATCH 058/170] 8379203: [BACKOUT] Remove some unused code in generateOopMap.cpp Reviewed-by: liach, coleenp --- src/hotspot/share/interpreter/oopMapCache.cpp | 28 ++++++++++- src/hotspot/share/oops/generateOopMap.cpp | 50 +++++++++++++++++-- src/hotspot/share/oops/generateOopMap.hpp | 41 +++++++++++++-- 3 files changed, 111 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/interpreter/oopMapCache.cpp b/src/hotspot/share/interpreter/oopMapCache.cpp index 3769a473e3d..29d6825d3e5 100644 --- a/src/hotspot/share/interpreter/oopMapCache.cpp +++ b/src/hotspot/share/interpreter/oopMapCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,10 +78,15 @@ class OopMapForCacheEntry: public GenerateOopMap { int _stack_top; virtual bool report_results() const { return false; } + virtual bool possible_gc_point (BytecodeStream *bcs); + virtual void fill_stackmap_prolog (int nof_gc_points); + virtual void fill_stackmap_epilog (); virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top); + virtual void fill_init_vars (GrowableArray *init_vars); + public: OopMapForCacheEntry(const methodHandle& method, int bci, OopMapCacheEntry *entry); @@ -114,6 +119,27 @@ bool OopMapForCacheEntry::compute_map(Thread* current) { return true; } + +bool OopMapForCacheEntry::possible_gc_point(BytecodeStream *bcs) { + return false; // We are not reporting any result. We call result_for_basicblock directly +} + + +void OopMapForCacheEntry::fill_stackmap_prolog(int nof_gc_points) { + // Do nothing +} + + +void OopMapForCacheEntry::fill_stackmap_epilog() { + // Do nothing +} + + +void OopMapForCacheEntry::fill_init_vars(GrowableArray *init_vars) { + // Do nothing +} + + void OopMapForCacheEntry::fill_stackmap_for_opcodes(BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, diff --git a/src/hotspot/share/oops/generateOopMap.cpp b/src/hotspot/share/oops/generateOopMap.cpp index db1e8b4548b..97d8bf3d526 100644 --- a/src/hotspot/share/oops/generateOopMap.cpp +++ b/src/hotspot/share/oops/generateOopMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -391,6 +391,7 @@ void CellTypeState::print(outputStream *os) { // void GenerateOopMap::initialize_bb() { + _gc_points = 0; _bb_count = 0; _bb_hdr_bits.reinitialize(method()->code_size()); } @@ -408,7 +409,7 @@ void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) { } -void GenerateOopMap::mark_bbheaders() { +void GenerateOopMap::mark_bbheaders_and_count_gc_points() { initialize_bb(); bool fellThrough = false; // False to get first BB marked. @@ -444,6 +445,9 @@ void GenerateOopMap::mark_bbheaders() { default: break; } + + if (possible_gc_point(&bcs)) + _gc_points++; } } @@ -1047,6 +1051,9 @@ void GenerateOopMap::setup_method_entry_state() { // Initialize CellState type of arguments methodsig_to_effect(method()->signature(), method()->is_static(), vars()); + // If some references must be pre-assigned to null, then set that up + initialize_vars(); + // This is the start state merge_state_into_bb(&_basic_blocks[0]); @@ -1070,6 +1077,27 @@ void GenerateOopMap::update_basic_blocks(int bci, int delta, } } +// +// Initvars handling +// + +void GenerateOopMap::initialize_vars() { + for (int k = 0; k < _init_vars->length(); k++) + _state[_init_vars->at(k)] = CellTypeState::make_slot_ref(k); +} + +void GenerateOopMap::add_to_ref_init_set(int localNo) { + + if (TraceNewOopMapGeneration) + tty->print_cr("Added init vars: %d", localNo); + + // Is it already in the set? + if (_init_vars->contains(localNo) ) + return; + + _init_vars->append(localNo); +} + // // Interpreration code // @@ -1644,6 +1672,7 @@ void GenerateOopMap::ppload(CellTypeState *out, int loc_no) { if (vcts.can_be_uninit()) { // It is a ref-uninit conflict (at least). If there are other // problems, we'll get them in the next round + add_to_ref_init_set(loc_no); vcts = out1; } else { // It wasn't a ref-uninit conflict. So must be a @@ -2036,6 +2065,7 @@ GenerateOopMap::GenerateOopMap(const methodHandle& method) { // We have to initialize all variables here, that can be queried directly _method = method; _max_locals=0; + _init_vars = nullptr; #ifndef PRODUCT // If we are doing a detailed trace, include the regular trace information. @@ -2065,6 +2095,7 @@ bool GenerateOopMap::compute_map(Thread* current) { _max_stack = method()->max_stack(); _has_exceptions = (method()->has_exception_handler()); _nof_refval_conflicts = 0; + _init_vars = new GrowableArray(5); // There are seldom more than 5 init_vars _report_result = false; _report_result_for_send = false; _new_var_map = nullptr; @@ -2088,6 +2119,8 @@ bool GenerateOopMap::compute_map(Thread* current) { // if no code - do nothing // compiler needs info if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) { + fill_stackmap_prolog(0); + fill_stackmap_epilog(); return true; } // Step 1: Compute all jump targets and their return value @@ -2096,7 +2129,7 @@ bool GenerateOopMap::compute_map(Thread* current) { // Step 2: Find all basic blocks and count GC points if (!_got_error) - mark_bbheaders(); + mark_bbheaders_and_count_gc_points(); // Step 3: Calculate stack maps if (!_got_error) @@ -2153,6 +2186,9 @@ void GenerateOopMap::report_result() { // We now want to report the result of the parse _report_result = true; + // Prolog code + fill_stackmap_prolog(_gc_points); + // Mark everything changed, then do one interpretation pass. for (int i = 0; i<_bb_count; i++) { if (_basic_blocks[i].is_reachable()) { @@ -2161,6 +2197,14 @@ void GenerateOopMap::report_result() { } } + // Note: Since we are skipping dead-code when we are reporting results, then + // the no. of encountered gc-points might be fewer than the previously number + // we have counted. (dead-code is a pain - it should be removed before we get here) + fill_stackmap_epilog(); + + // Report initvars + fill_init_vars(_init_vars); + _report_result = false; } diff --git a/src/hotspot/share/oops/generateOopMap.hpp b/src/hotspot/share/oops/generateOopMap.hpp index 7c445887ee7..0da3779d463 100644 --- a/src/hotspot/share/oops/generateOopMap.hpp +++ b/src/hotspot/share/oops/generateOopMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -348,15 +348,17 @@ class GenerateOopMap { // Basicblock info BasicBlock * _basic_blocks; // Array of basicblock info + int _gc_points; int _bb_count; ResourceBitMap _bb_hdr_bits; // Basicblocks methods void initialize_bb (); - void mark_bbheaders(); + void mark_bbheaders_and_count_gc_points(); bool is_bb_header (int bci) const { return _bb_hdr_bits.at(bci); } + int gc_points () const { return _gc_points; } int bb_count () const { return _bb_count; } void set_bbmark_bit (int bci); BasicBlock * get_basic_block_at (int bci) const; @@ -417,6 +419,12 @@ class GenerateOopMap { void report_result (); + // Initvars + GrowableArray * _init_vars; + + void initialize_vars (); + void add_to_ref_init_set (int localNo); + // Conflicts rewrite logic bool _conflict; // True, if a conflict occurred during interpretation int _nof_refval_conflicts; // No. of conflicts that require rewrites @@ -442,7 +450,7 @@ class GenerateOopMap { int binsToHold (int no) { return ((no+(BitsPerWord-1))/BitsPerWord); } char *state_vec_to_string (CellTypeState* vec, int len); - // Helper method. If the current instruction + // Helper method. Can be used in subclasses to fx. calculate gc_points. If the current instruction // is a control transfer, then calls the jmpFct all possible destinations. void ret_jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int varNo,int *data); bool jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int *data); @@ -472,7 +480,14 @@ class GenerateOopMap { bool monitor_safe() { return _monitor_safe; } // Specialization methods. Intended use: + // - possible_gc_point must return true for every bci for which the stackmaps must be returned + // - fill_stackmap_prolog is called just before the result is reported. The arguments tells the estimated + // number of gc points // - fill_stackmap_for_opcodes is called once for each bytecode index in order (0...code_length-1) + // - fill_stackmap_epilog is called after all results has been reported. Note: Since the algorithm does not report + // stackmaps for deadcode, fewer gc_points might have been encountered than assumed during the epilog. It is the + // responsibility of the subclass to count the correct number. + // - fill_init_vars are called once with the result of the init_vars computation // // All these methods are used during a call to: compute_map. Note: Non of the return results are valid // after compute_map returns, since all values are allocated as resource objects. @@ -480,10 +495,15 @@ class GenerateOopMap { // All virtual method must be implemented in subclasses virtual bool allow_rewrites () const { return false; } virtual bool report_results () const { return true; } + virtual bool report_init_vars () const { return true; } + virtual bool possible_gc_point (BytecodeStream *bcs) { ShouldNotReachHere(); return false; } + virtual void fill_stackmap_prolog (int nof_gc_points) { ShouldNotReachHere(); } + virtual void fill_stackmap_epilog () { ShouldNotReachHere(); } virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stackTop) { ShouldNotReachHere(); } + virtual void fill_init_vars (GrowableArray *init_vars) { ShouldNotReachHere();; } }; // @@ -493,12 +513,19 @@ class GenerateOopMap { class ResolveOopMapConflicts: public GenerateOopMap { private: + bool _must_clear_locals; + virtual bool report_results() const { return false; } + virtual bool report_init_vars() const { return true; } virtual bool allow_rewrites() const { return true; } + virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } + virtual void fill_stackmap_prolog (int nof_gc_points) {} + virtual void fill_stackmap_epilog () {} virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top) {} + virtual void fill_init_vars (GrowableArray *init_vars) { _must_clear_locals = init_vars->length() > 0; } #ifndef PRODUCT // Statistics @@ -508,9 +535,10 @@ class ResolveOopMapConflicts: public GenerateOopMap { #endif public: - ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { } + ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { _must_clear_locals = false; }; methodHandle do_potential_rewrite(TRAPS); + bool must_clear_locals() const { return _must_clear_locals; } }; @@ -521,11 +549,16 @@ class GeneratePairingInfo: public GenerateOopMap { private: virtual bool report_results() const { return false; } + virtual bool report_init_vars() const { return false; } virtual bool allow_rewrites() const { return false; } + virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } + virtual void fill_stackmap_prolog (int nof_gc_points) {} + virtual void fill_stackmap_epilog () {} virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top) {} + virtual void fill_init_vars (GrowableArray *init_vars) {} public: GeneratePairingInfo(const methodHandle& method) : GenerateOopMap(method) {}; From 0fbf58d8ff4fae370d5a839e59cebf713a1f1e5a Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Wed, 4 Mar 2026 17:33:32 +0000 Subject: [PATCH 059/170] 8372353: API to compute the byte length of a String encoded in a given Charset Reviewed-by: rriggs, naoto, vyazici --- .../share/classes/java/lang/String.java | 95 +++++++++++++- test/jdk/java/lang/String/Encodings.java | 8 +- test/jdk/java/lang/String/Exceptions.java | 13 +- test/jdk/sun/nio/cs/TestStringCoding.java | 10 +- .../lang/foreign/StringLoopJmhBenchmark.java | 122 ++++++++++++++++++ 5 files changed, 235 insertions(+), 13 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/StringLoopJmhBenchmark.java diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index fc05febdb45..c6c08ed4473 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1133,6 +1133,34 @@ public final class String return Arrays.copyOf(dst, dp); } + // This follows the implementation of encodeASCII and encode8859_1 + private static int encodedLengthASCIIor8859_1(byte coder, byte[] val) { + if (coder == LATIN1) { + return val.length; + } + int len = val.length >> 1; + int dp = 0; + int sp = 0; + int sl = len; + while (sp < sl) { + char c = StringUTF16.getChar(val, sp); + if (c >= Character.MIN_HIGH_SURROGATE) { + break; + } + dp++; + sp++; + } + while (sp < sl) { + char c = StringUTF16.getChar(val, sp++); + if (Character.isHighSurrogate(c) && sp < sl && + Character.isLowSurrogate(StringUTF16.getChar(val, sp))) { + sp++; + } + dp++; + } + return dp; + } + //------------------------------ utf8 ------------------------------------ /** @@ -1467,6 +1495,27 @@ public final class String return Arrays.copyOf(dst, dp); } + // This follows the implementation of encodeUTF8 + private static int encodedLengthUTF8(byte coder, byte[] val) { + if (coder == UTF16) { + return encodedLengthUTF8_UTF16(val, null); + } + int positives = StringCoding.countPositives(val, 0, val.length); + if (positives == val.length) { + return positives; + } + int dp = positives; + for (int i = dp; i < val.length; i++) { + byte c = val[i]; + if (c < 0) { + dp += 2; + } else { + dp++; + } + } + return dp; + } + /** * {@return the byte array obtained by first decoding {@code val} with * UTF-16, and then encoding the result with UTF-8} @@ -1484,11 +1533,8 @@ public final class String int sl = val.length >> 1; // UTF-8 encoded can be as much as 3 times the string length // For very large estimate, (as in overflow of 32 bit int), precompute the exact size - long allocLen = (sl * 3 < 0) ? computeSizeUTF8_UTF16(val, exClass) : sl * 3; - if (allocLen > (long)Integer.MAX_VALUE) { - throw new OutOfMemoryError("Required length exceeds implementation limit"); - } - byte[] dst = new byte[(int) allocLen]; + int allocLen = (sl * 3 < 0) ? encodedLengthUTF8_UTF16(val, exClass) : sl * 3; + byte[] dst = new byte[allocLen]; while (sp < sl) { // ascii fast loop; char c = StringUTF16.getChar(val, sp); @@ -1547,11 +1593,20 @@ public final class String * @param The exception type parameter to enable callers to avoid * having to declare the exception */ - private static long computeSizeUTF8_UTF16(byte[] val, Class exClass) throws E { + private static int encodedLengthUTF8_UTF16(byte[] val, Class exClass) throws E { long dp = 0L; int sp = 0; int sl = val.length >> 1; + while (sp < sl) { + // ascii fast loop; + char c = StringUTF16.getChar(val, sp); + if (c >= '\u0080') { + break; + } + dp++; + sp++; + } while (sp < sl) { char c = StringUTF16.getChar(val, sp++); if (c < 0x80) { @@ -1580,7 +1635,10 @@ public final class String dp += 3; } } - return dp; + if (dp > (long)Integer.MAX_VALUE) { + throw new OutOfMemoryError("Required length exceeds implementation limit"); + } + return (int) dp; } /** @@ -2045,6 +2103,29 @@ public final class String return encode(Charset.defaultCharset(), coder(), value); } + /** + * {@return the length in bytes of this {@code String} encoded with the given {@link Charset}} + * + *

The returned length accounts for the replacement of malformed-input and unmappable-character + * sequences with the charset's default replacement byte array. The result will be the same value + * as {@link #getBytes(Charset) getBytes(cs).length}. + * + * @apiNote This method provides equivalent or better performance than {@link #getBytes(Charset) + * getBytes(cs).length}. + * + * @param cs The {@link Charset} used to the compute the length + * @since 27 + */ + public int encodedLength(Charset cs) { + Objects.requireNonNull(cs); + if (cs == UTF_8.INSTANCE) { + return encodedLengthUTF8(coder, value); + } else if (cs == ISO_8859_1.INSTANCE || cs == US_ASCII.INSTANCE) { + return encodedLengthASCIIor8859_1(coder, value); + } + return getBytes(cs).length; + } + boolean bytesCompatible(Charset charset, int srcIndex, int numChars) { if (isLatin1()) { if (charset == ISO_8859_1.INSTANCE) { diff --git a/test/jdk/java/lang/String/Encodings.java b/test/jdk/java/lang/String/Encodings.java index 4714815026e..7974157ede0 100644 --- a/test/jdk/java/lang/String/Encodings.java +++ b/test/jdk/java/lang/String/Encodings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4085160 4139951 5005831 + * @bug 4085160 4139951 5005831 8372353 * @summary Test that required character encodings are supported */ @@ -106,6 +106,10 @@ public class Encodings { if (!equals(bs, bytes)) throw new Exception(charset + ": String.getBytes failed"); + /* String.encodedLength(Charset charset) */ + if (bs.length != str.encodedLength(charset)) + throw new Exception(charset + ": String.encodedLength failed"); + // Calls to String.getBytes(Charset) shouldn't automatically // use the cached thread-local encoder. if (charset.name().equals("UTF-16BE")) { diff --git a/test/jdk/java/lang/String/Exceptions.java b/test/jdk/java/lang/String/Exceptions.java index 3ba7792f424..15ffe3eac20 100644 --- a/test/jdk/java/lang/String/Exceptions.java +++ b/test/jdk/java/lang/String/Exceptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 4472841 4703640 4705681 4705683 4833095 5005831 + * @bug 4472841 4703640 4705681 4705683 4833095 5005831 8372353 * @summary Verify that constructor exceptions are thrown as expected. */ @@ -397,6 +397,14 @@ public class Exceptions { }}); } + private static void encodedLength() { + System.out.println("encodedLength(Charset charset)"); + tryCatch(" null", NullPointerException.class, new Runnable() { + public void run() { + "foo".encodedLength((Charset)null); + }}); + } + private static void contentEquals() { System.out.println("contentEquals(StringBuffer sb)"); tryCatch(" null", NullPointerException.class, new Runnable() { @@ -640,6 +648,7 @@ public class Exceptions { // getBytes(Locale) // getBytes(String) // getBytes(Charset) + encodedLength(); // encodedLength(Charset) contentEquals(); // contentEquals(StringBuffer) compareTo(); // compareTo(String), compareTo(Object) compareToIgnoreCase();// compareToIgnoreCase(String) diff --git a/test/jdk/sun/nio/cs/TestStringCoding.java b/test/jdk/sun/nio/cs/TestStringCoding.java index d708ef180a2..b81ffb07d20 100644 --- a/test/jdk/sun/nio/cs/TestStringCoding.java +++ b/test/jdk/sun/nio/cs/TestStringCoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 6636323 6636319 7040220 7096080 7183053 8080248 8054307 + * @bug 6636323 6636319 7040220 7096080 7183053 8080248 8054307 8372353 * @summary Test if StringCoding and NIO result have the same de/encoding result * @library /test/lib * @modules java.base/sun.nio.cs @@ -169,6 +169,12 @@ public class TestStringCoding { if (!Arrays.equals(baSC, baNIO)) { throw new RuntimeException("getBytes(cs) failed -> " + cs.name()); } + //encodedLength(cs); + int encodedLength = str.encodedLength(cs); + if (baSC.length != encodedLength) { + throw new RuntimeException(String.format("encodedLength failed (%d != %d) -> %s", + baSC.length, encodedLength, cs.name())); + } return baSC; } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/StringLoopJmhBenchmark.java b/test/micro/org/openjdk/bench/java/lang/foreign/StringLoopJmhBenchmark.java new file mode 100644 index 00000000000..1733b73886e --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/StringLoopJmhBenchmark.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2026, Google LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.foreign; + +import java.nio.charset.StandardCharsets; +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.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.annotations.State; + +@Warmup(time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(1) +@State(Scope.Benchmark) +public class StringLoopJmhBenchmark { + @Param({"10", "100", "1000", "100000"}) + int stringLength; + + @Param({"ASCII", "LATIN1", "UTF16"}) + String encoding; + + String stringData; + + @Setup + public void setUp() { + stringData = ""; + + // Character at the _end_ to affect if we hit + // - ASCII = compact strings and compatible with UTF-8 + // - LATIN1 = compact strings but not compatible with UTF-8 + // - UTF16 = 2-byte char storage and not compatible with UTF-8 + String c; + if (encoding.equals("ASCII")) { + c = "a"; + } else if (encoding.equals("LATIN1")) { + c = "\u00C4"; + } else if (encoding.equals("UTF16")) { + c = "\u2603"; + } else { + throw new IllegalArgumentException("Unknown encoding: " + encoding); + } + + var stringDataBuilder = new StringBuilder(stringLength + 1); + while (stringDataBuilder.length() < stringLength) { + stringDataBuilder.append((char) (Math.random() * 26) + 'a'); + } + stringData = stringDataBuilder.append(c).toString(); + } + + @Benchmark + public int utf8LenByLoop() { + final String s = stringData; + final int len = s.length(); + + // ASCII prefix strings. + int idx = 0; + for (char c; idx < len && (c = s.charAt(idx)) < 0x80; ++idx) {} + + // Entire string was ASCII. + if (idx == len) { + return len; + } + + int utf8Len = len; + for (char c; idx < len; ++idx) { + c = s.charAt(idx); + if (c < 0x80) { + utf8Len++; + } else if (c < 0x800) { + utf8Len += 2; + } else { + utf8Len += 3; + if (Character.isSurrogate(c)) { + int cp = Character.codePointAt(s, idx); + if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) { + throw new RuntimeException("Unpaired surrogate"); + } + idx++; + } + } + } + return utf8Len; + } + + @Benchmark + public int getBytes() throws Exception { + return stringData.getBytes(StandardCharsets.UTF_8).length; + } + + @Benchmark + public int encodedLength() throws Exception { + return stringData.encodedLength(StandardCharsets.UTF_8); + } +} From c52d7b7cbc89548c3e9cd68a29ff0cec04888b09 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 4 Mar 2026 18:50:13 +0000 Subject: [PATCH 060/170] 8378878: Refactor java/nio/channels/AsynchronousSocketChannel test to use JUnit Reviewed-by: alanb --- .../CompletionHandlerRelease.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/test/jdk/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java b/test/jdk/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java index 7abbf064b40..962d7728a55 100644 --- a/test/jdk/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java +++ b/test/jdk/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test * @bug 8202252 - * @run testng CompletionHandlerRelease + * @run junit CompletionHandlerRelease * @summary Verify that reference to CompletionHandler is cleared after use */ @@ -44,10 +44,12 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; public class CompletionHandlerRelease { @Test @@ -132,16 +134,16 @@ public class CompletionHandlerRelease { } } - private AsynchronousChannelGroup GROUP; + private static AsynchronousChannelGroup GROUP; - @BeforeTest - void setup() throws IOException { + @BeforeAll + static void setup() throws IOException { GROUP = AsynchronousChannelGroup.withFixedThreadPool(2, Executors.defaultThreadFactory()); } - @AfterTest - void cleanup() throws IOException { + @AfterAll + static void cleanup() throws IOException { GROUP.shutdownNow(); } @@ -199,13 +201,13 @@ public class CompletionHandlerRelease { } } - private void waitForRefToClear(Reference ref, ReferenceQueue queue) + private static void waitForRefToClear(Reference ref, ReferenceQueue queue) throws InterruptedException { Reference r; while ((r = queue.remove(20)) == null) { System.gc(); } - assertEquals(r, ref); + assertSame(ref, r); assertNull(r.get()); } } From 9d1d0c6f0553c5f042351d1def385589015fefd6 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Wed, 4 Mar 2026 19:46:06 +0000 Subject: [PATCH 061/170] 8379166: Upstream redundant diffs fixed in Valhalla - Part 1 Reviewed-by: rriggs --- .../classes/java/io/ObjectInputStream.java | 2 +- .../share/classes/java/lang/Boolean.java | 4 --- .../share/classes/java/lang/Byte.java | 1 - .../share/classes/java/lang/Class.java | 9 ++++--- .../share/classes/java/lang/Short.java | 1 - .../java/lang/doc-files/ValueBased.html | 22 ++++++++-------- .../classes/java/lang/invoke/MemberName.java | 25 ++++++++++--------- .../java/lang/invoke/MethodHandleProxies.java | 2 +- .../classes/java/lang/reflect/Proxy.java | 5 ++-- .../share/classes/java/util/WeakHashMap.java | 2 +- .../classfile/impl/DirectClassBuilder.java | 1 - .../impl/verifier/VerificationTable.java | 2 +- .../jdk/internal/jimage/ImageReader.java | 1 + src/java.base/share/classes/module-info.java | 9 +++---- .../include/classfile_constants.h.template | 2 +- 15 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index daed5f3cce5..cd6bd7683f7 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -2219,7 +2219,7 @@ public class ObjectInputStream * mechanism marks the record as having an exception. * Null is returned from readRecord and later the exception is thrown at * the exit of {@link #readObject(Class)}. - **/ + */ private Object readRecord(ObjectStreamClass desc) throws IOException { ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout(); if (slots.length != 1) { diff --git a/src/java.base/share/classes/java/lang/Boolean.java b/src/java.base/share/classes/java/lang/Boolean.java index 4c24e98a549..49ab80edfea 100644 --- a/src/java.base/share/classes/java/lang/Boolean.java +++ b/src/java.base/share/classes/java/lang/Boolean.java @@ -28,14 +28,10 @@ package java.lang; import jdk.internal.vm.annotation.IntrinsicCandidate; import java.lang.constant.Constable; -import java.lang.constant.ConstantDesc; import java.lang.constant.ConstantDescs; import java.lang.constant.DynamicConstantDesc; import java.util.Optional; -import static java.lang.constant.ConstantDescs.BSM_GET_STATIC_FINAL; -import static java.lang.constant.ConstantDescs.CD_Boolean; - /** * The {@code Boolean} class is the {@linkplain * java.lang##wrapperClass wrapper class} for values of the primitive diff --git a/src/java.base/share/classes/java/lang/Byte.java b/src/java.base/share/classes/java/lang/Byte.java index 0f3f7f40d05..c2c03e7a3c2 100644 --- a/src/java.base/share/classes/java/lang/Byte.java +++ b/src/java.base/share/classes/java/lang/Byte.java @@ -36,7 +36,6 @@ import java.util.Optional; import static java.lang.constant.ConstantDescs.BSM_EXPLICIT_CAST; import static java.lang.constant.ConstantDescs.CD_byte; -import static java.lang.constant.ConstantDescs.CD_int; import static java.lang.constant.ConstantDescs.DEFAULT_NAME; /** diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index eab1993a2b4..8a2f722f3dd 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -224,9 +224,9 @@ public final class Class implements java.io.Serializable, AnnotatedElement, TypeDescriptor.OfField>, Constable { - private static final int ANNOTATION= 0x00002000; - private static final int ENUM = 0x00004000; - private static final int SYNTHETIC = 0x00001000; + private static final int ANNOTATION = 0x00002000; + private static final int ENUM = 0x00004000; + private static final int SYNTHETIC = 0x00001000; private static native void registerNatives(); static { @@ -1390,6 +1390,7 @@ public final class Class implements java.io.Serializable, // INNER_CLASS forbids. INNER_CLASS allows PRIVATE, PROTECTED, // and STATIC, which are not allowed on Location.CLASS. // Use getClassFileAccessFlags to expose SUPER status. + // Arrays need to use PRIVATE/PROTECTED from its component modifiers. var location = (isMemberClass() || isLocalClass() || isAnonymousClass() || isArray()) ? AccessFlag.Location.INNER_CLASS : @@ -3779,7 +3780,7 @@ public final class Class implements java.io.Serializable, * @since 1.8 */ public AnnotatedType[] getAnnotatedInterfaces() { - return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); + return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this); } private native Class getNestHost0(); diff --git a/src/java.base/share/classes/java/lang/Short.java b/src/java.base/share/classes/java/lang/Short.java index 920500a7fa3..14f7a267165 100644 --- a/src/java.base/share/classes/java/lang/Short.java +++ b/src/java.base/share/classes/java/lang/Short.java @@ -35,7 +35,6 @@ import java.lang.constant.DynamicConstantDesc; import java.util.Optional; import static java.lang.constant.ConstantDescs.BSM_EXPLICIT_CAST; -import static java.lang.constant.ConstantDescs.CD_int; import static java.lang.constant.ConstantDescs.CD_short; import static java.lang.constant.ConstantDescs.DEFAULT_NAME; diff --git a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html index 6a935afe04b..3b860ce0534 100644 --- a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html +++ b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html @@ -30,35 +30,35 @@

{@index "Value-based Classes"}

-Some classes, such as java.lang.Integer and -java.time.LocalDate, are value-based. +Some classes, such as {@code java.lang.Integer} and +{@code java.time.LocalDate}, are value-based. A value-based class has the following properties:
  • the class declares only final instance fields (though these may contain references to mutable objects);
  • -
  • the class's implementations of equals, hashCode, - and toString compute their results solely from the values +
  • the class's implementations of {@code equals}, {@code hashCode}, + and {@code toString} compute their results solely from the values of the class's instance fields (and the members of the objects they reference), not from the instance's identity;
  • the class's methods treat instances as freely substitutable - when equal, meaning that interchanging any two instances x and - y that are equal according to equals() produces no + when equal, meaning that interchanging any two instances {@code x} and + {@code y} that are equal according to {@code equals()} produces no visible change in the behavior of the class's methods;
  • the class performs no synchronization using an instance's monitor;
  • -
  • the class does not declare (or has deprecated any) accessible constructors;
  • +
  • the class does not declare (or discourages use of) accessible constructors;
  • the class does not provide any instance creation mechanism that promises a unique identity on each method call—in particular, any factory method's contract must allow for the possibility that if two independently-produced - instances are equal according to equals(), they may also be - equal according to ==;
  • -
  • the class is final, and extends either Object or a hierarchy of + instances are equal according to {@code equals()}, they may also be + equal according to {@code ==};
  • +
  • the class is final, and extends either {@code Object} or a hierarchy of abstract classes that declare no instance fields or instance initializers and whose constructors are empty.

When two instances of a value-based class are equal (according to `equals`), a program should not attempt to distinguish between their identities, whether directly via reference - equality or indirectly via an appeal to synchronization, identity hashing, + equality {@code ==} or indirectly via an appeal to synchronization, identity hashing, serialization, or any other identity-sensitive mechanism.

Synchronization on instances of value-based classes is strongly discouraged, diff --git a/src/java.base/share/classes/java/lang/invoke/MemberName.java b/src/java.base/share/classes/java/lang/invoke/MemberName.java index 918d1b10791..d320ad11ade 100644 --- a/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -408,11 +408,12 @@ final class MemberName implements Member, Cloneable { // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo // unofficial modifier flags, used by HotSpot: - static final int BRIDGE = 0x00000040; - static final int VARARGS = 0x00000080; - static final int SYNTHETIC = 0x00001000; - static final int ANNOTATION= 0x00002000; - static final int ENUM = 0x00004000; + static final int BRIDGE = 0x00000040; + static final int VARARGS = 0x00000080; + static final int SYNTHETIC = 0x00001000; + static final int ANNOTATION = 0x00002000; + static final int ENUM = 0x00004000; + /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ public boolean isBridge() { return allFlagsSet(IS_METHOD | BRIDGE); @@ -426,19 +427,19 @@ final class MemberName implements Member, Cloneable { return allFlagsSet(SYNTHETIC); } - static final String CONSTRUCTOR_NAME = ""; // the ever-popular + static final String CONSTRUCTOR_NAME = ""; // modifiers exported by the JVM: static final int RECOGNIZED_MODIFIERS = 0xFFFF; // private flags, not part of RECOGNIZED_MODIFIERS: static final int - IS_METHOD = MN_IS_METHOD, // method (not constructor) - IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor - IS_FIELD = MN_IS_FIELD, // field - IS_TYPE = MN_IS_TYPE, // nested type - CALLER_SENSITIVE = MN_CALLER_SENSITIVE, // @CallerSensitive annotation detected - TRUSTED_FINAL = MN_TRUSTED_FINAL; // trusted final field + IS_METHOD = MN_IS_METHOD, // method (not constructor) + IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor + IS_FIELD = MN_IS_FIELD, // field + IS_TYPE = MN_IS_TYPE, // nested type + CALLER_SENSITIVE = MN_CALLER_SENSITIVE, // @CallerSensitive annotation detected + TRUSTED_FINAL = MN_TRUSTED_FINAL; // trusted final field static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java index 16f5c7e59b8..8dac21c8968 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -344,7 +344,7 @@ public final class MethodHandleProxies { ClassLoaders.platformClassLoader() : loader))) .build(proxyDesc, clb -> { clb.withSuperclass(CD_Object) - .withFlags(ACC_FINAL | ACC_SYNTHETIC) + .withFlags(ACC_SUPER | ACC_FINAL | ACC_SYNTHETIC) .withInterfaceSymbols(ifaceDesc) // static and instance fields .withField(TYPE_NAME, CD_Class, ACC_PRIVATE | ACC_STATIC | ACC_FINAL) diff --git a/src/java.base/share/classes/java/lang/reflect/Proxy.java b/src/java.base/share/classes/java/lang/reflect/Proxy.java index b811deb863d..6ce8e80cdca 100644 --- a/src/java.base/share/classes/java/lang/reflect/Proxy.java +++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package java.lang.reflect; +import java.lang.classfile.ClassFile; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -467,7 +468,7 @@ public class Proxy implements java.io.Serializable { * Generate the specified proxy class. */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass(loader, proxyName, interfaces, - context.accessFlags() | Modifier.FINAL); + context.accessFlags() | Modifier.FINAL | ClassFile.ACC_SUPER); try { Class pc = JLA.defineClass(loader, proxyName, proxyClassFile, null, "__dynamic_proxy__"); diff --git a/src/java.base/share/classes/java/util/WeakHashMap.java b/src/java.base/share/classes/java/util/WeakHashMap.java index b5a27593840..1412d8f6ff9 100644 --- a/src/java.base/share/classes/java/util/WeakHashMap.java +++ b/src/java.base/share/classes/java/util/WeakHashMap.java @@ -25,8 +25,8 @@ package java.util; -import java.lang.ref.WeakReference; import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java index 0e82c545359..79c623bc31d 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java @@ -168,7 +168,6 @@ public final class DirectClassBuilder this.sizeHint = sizeHint; } - public byte[] build() { // The logic of this is very carefully ordered. We want to avoid diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java index 04276b8eeb8..eb3f5ee913d 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerificationTable.java @@ -321,7 +321,7 @@ class VerificationTable { return frame; } int offset_delta = _stream.get_u2(); - if (frame_type < SAME_LOCALS_1_STACK_ITEM_EXTENDED) { + if (frame_type <= RESERVED_END) { _verifier.classError("reserved frame type"); } if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java index c36e265ee2f..4c358820166 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java @@ -821,6 +821,7 @@ public final class ImageReader implements AutoCloseable { this.children = Collections.unmodifiableList(children); } } + /** * Resource node (e.g. a ".class" entry, or any other data resource). * diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index d20f6311bca..665b3a3b98d 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -135,7 +135,6 @@ module java.base { exports javax.security.auth.x500; exports javax.security.cert; - // additional qualified exports may be inserted at build time // see make/gensrc/GenModuleInfo.gmk @@ -147,11 +146,11 @@ module java.base { java.security.sasl; exports jdk.internal to jdk.incubator.vector; - // Note: all modules in the exported list participate in preview features - // and therefore if they use preview features they do not need to be - // compiled with "--enable-preview". + // Note: all modules in the exported list participate in preview features, + // normal or reflective. They do not need to be compiled with "--enable-preview" + // to use preview features and do not need to suppress "preview" warnings. // It is recommended for any modules that do participate that their - // module declaration be annotated with jdk.internal.javac.ParticipatesInPreview + // module declaration be annotated with jdk.internal.javac.ParticipatesInPreview. exports jdk.internal.javac to java.compiler, jdk.compiler; diff --git a/src/java.base/share/native/include/classfile_constants.h.template b/src/java.base/share/native/include/classfile_constants.h.template index fb022ec1fd4..4f96a0673ef 100644 --- a/src/java.base/share/native/include/classfile_constants.h.template +++ b/src/java.base/share/native/include/classfile_constants.h.template @@ -111,7 +111,7 @@ enum { JVM_CONSTANT_InvokeDynamic = 18, JVM_CONSTANT_Module = 19, JVM_CONSTANT_Package = 20, - JVM_CONSTANT_ExternalMax = 20 + JVM_CONSTANT_ExternalMax = 20 }; /* JVM_CONSTANT_MethodHandle subtypes */ From 08c8520b39083ec6354dc5df2f18c1f4c3588053 Mon Sep 17 00:00:00 2001 From: Patrick Strawderman Date: Wed, 4 Mar 2026 20:04:30 +0000 Subject: [PATCH 062/170] 8378698: Optimize Base64.Encoder#encodeToString Reviewed-by: liach, rriggs --- .../share/classes/java/util/Base64.java | 6 +- .../bench/java/util/Base64EncodeToString.java | 55 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/util/Base64EncodeToString.java diff --git a/src/java.base/share/classes/java/util/Base64.java b/src/java.base/share/classes/java/util/Base64.java index ed1a4a8d638..fd714050149 100644 --- a/src/java.base/share/classes/java/util/Base64.java +++ b/src/java.base/share/classes/java/util/Base64.java @@ -32,6 +32,8 @@ import java.io.OutputStream; import java.nio.ByteBuffer; import sun.nio.cs.ISO_8859_1; +import jdk.internal.access.JavaLangAccess; +import jdk.internal.access.SharedSecrets; import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.IntrinsicCandidate; @@ -201,6 +203,7 @@ public final class Base64 { * @since 1.8 */ public static class Encoder { + private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); private final byte[] newline; private final int linemax; @@ -344,10 +347,9 @@ public final class Base64 { * the byte array to encode * @return A String containing the resulting Base64 encoded characters */ - @SuppressWarnings("deprecation") public String encodeToString(byte[] src) { byte[] encoded = encode(src); - return new String(encoded, 0, 0, encoded.length); + return JLA.uncheckedNewStringWithLatin1Bytes(encoded); } /** diff --git a/test/micro/org/openjdk/bench/java/util/Base64EncodeToString.java b/test/micro/org/openjdk/bench/java/util/Base64EncodeToString.java new file mode 100644 index 00000000000..5b259230341 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/Base64EncodeToString.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.micro.bench.java.util; + +import org.openjdk.jmh.annotations.*; + +import java.util.Base64; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@State(Scope.Benchmark) +@Warmup(iterations = 5, time = 2) +@Measurement(iterations = 5, time = 2) +@Fork(value = 2) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +public class Base64EncodeToString { + + private byte[] input; + + @Param({"10", "100", "1000", "10000"}) + private int inputSize; + + @Setup + public void setup() { + Random r = new Random(1123); + input = new byte[inputSize]; + r.nextBytes(input); + } + + @Benchmark + public String testEncodeToString() { + return Base64.getEncoder().encodeToString(input); + } +} + From 1f4a7bbb9d67fdaaf63a70d92df895aea41ad201 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 4 Mar 2026 22:42:19 +0000 Subject: [PATCH 063/170] 8379040: Remove inclusion of allocation.hpp from atomicAccess.hpp Reviewed-by: iwalulya, dholmes --- src/hotspot/share/opto/phasetype.hpp | 3 ++- src/hotspot/share/runtime/atomicAccess.hpp | 6 +++--- src/hotspot/share/utilities/bitMap.hpp | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index f388dc6cdc6..ce432fbfc01 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_OPTO_PHASETYPE_HPP #define SHARE_OPTO_PHASETYPE_HPP +#include "memory/allocation.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/stringUtils.hpp" diff --git a/src/hotspot/share/runtime/atomicAccess.hpp b/src/hotspot/share/runtime/atomicAccess.hpp index c9a2dfb9383..46330cffdb2 100644 --- a/src/hotspot/share/runtime/atomicAccess.hpp +++ b/src/hotspot/share/runtime/atomicAccess.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #define SHARE_RUNTIME_ATOMICACCESS_HPP #include "cppstdlib/type_traits.hpp" -#include "memory/allocation.hpp" +#include "memory/allStatic.hpp" #include "metaprogramming/enableIf.hpp" #include "metaprogramming/primitiveConversions.hpp" #include "runtime/orderAccess.hpp" @@ -829,7 +829,7 @@ class AtomicAccess::PlatformBitops {}; template -class ScopedFenceGeneral: public StackObj { +class ScopedFenceGeneral { public: void prefix() {} void postfix() {} diff --git a/src/hotspot/share/utilities/bitMap.hpp b/src/hotspot/share/utilities/bitMap.hpp index 5ee462bbe47..17bf437ecae 100644 --- a/src/hotspot/share/utilities/bitMap.hpp +++ b/src/hotspot/share/utilities/bitMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "utilities/globalDefinitions.hpp" // Forward decl; +class Arena; class BitMapClosure; // Operations for bitmaps represented as arrays of unsigned integers. From c9da76bf33a5e44eb238e3b29eda523e7754b7b6 Mon Sep 17 00:00:00 2001 From: Xiaohong Gong Date: Thu, 5 Mar 2026 01:57:03 +0000 Subject: [PATCH 064/170] 8377449: Strengthen vector IR validation in TestVectorAlgorithms.java for AArch64 Reviewed-by: mhaessig, epeter --- .../vectorization/TestVectorAlgorithms.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java index e02563c2fc2..785a6de30a0 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java @@ -272,8 +272,10 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.ADD_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeature = {"sse4.1", "true"}) - // Note: also works with NEON/asimd, but only with TieredCompilation. + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIf = {"TieredCompilation", "true"}) + // IR check only works with TieredCompilation. Needs to make it + // work with -XX:-TieredCompilation in future (see JDK-8378640). public Object iotaI_VectorAPI(int[] r) { return VectorAlgorithmsImpl.iotaI_VectorAPI(r); } @@ -360,7 +362,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.ADD_REDUCTION_V, "> 0", IRNode.MUL_VF, "> 0"}, - applyIfCPUFeature = {"sse4.1", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, applyIf = {"UseSuperWord", "true"}) public float dotProductF_VectorAPI_naive(float[] a, float[] b) { return VectorAlgorithmsImpl.dotProductF_VectorAPI_naive(a, b); @@ -370,7 +372,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.ADD_REDUCTION_V, "> 0", IRNode.MUL_VF, "> 0"}, - applyIfCPUFeature = {"sse4.1", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, applyIf = {"UseSuperWord", "true"}) public float dotProductF_VectorAPI_reduction_after_loop(float[] a, float[] b) { return VectorAlgorithmsImpl.dotProductF_VectorAPI_reduction_after_loop(a, b); @@ -392,7 +394,8 @@ public class TestVectorAlgorithms { IRNode.MUL_VI, IRNode.VECTOR_SIZE_8, "> 0", IRNode.ADD_VI, IRNode.VECTOR_SIZE_8, "> 0", IRNode.ADD_REDUCTION_VI, "> 0"}, - applyIfCPUFeature = {"avx2", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "sve", "true"}, + applyIf = {"MaxVectorSize", ">=32"}) public int hashCodeB_VectorAPI_v1(byte[] a) { return VectorAlgorithmsImpl.hashCodeB_VectorAPI_v1(a); } @@ -402,7 +405,7 @@ public class TestVectorAlgorithms { IRNode.MUL_VI, "> 0", IRNode.ADD_VI, "> 0", IRNode.ADD_REDUCTION_VI, "> 0"}, - applyIfCPUFeature = {"avx2", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) public int hashCodeB_VectorAPI_v2(byte[] a) { return VectorAlgorithmsImpl.hashCodeB_VectorAPI_v2(a); } @@ -506,7 +509,7 @@ public class TestVectorAlgorithms { IRNode.VECTOR_TEST, "> 0", IRNode.COMPRESS_VI, "> 0", IRNode.STORE_VECTOR_MASKED, "> 0"}, - applyIfCPUFeature = {"avx2", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "sve", "true"}) public Object filterI_VectorAPI(int[] a, int[] r, int threshold) { return VectorAlgorithmsImpl.filterI_VectorAPI(a, r, threshold); } @@ -526,7 +529,10 @@ public class TestVectorAlgorithms { IRNode.OR_V_MASK, "> 0", IRNode.ADD_VI, "> 0", IRNode.ADD_REDUCTION_VI, "> 0"}, - applyIfCPUFeatureOr = {"avx512", "true", "sve", "true"}) + applyIfCPUFeatureOr = {"avx512", "true", "sve", "true"}, + applyIf = {"TieredCompilation", "true"}) + // IR check only works with TieredCompilation. Needs to make it + // work with -XX:-TieredCompilation in future (see JDK-8378640). public int reduceAddIFieldsX4_VectorAPI(int[] oops, int[] mem) { return VectorAlgorithmsImpl.reduceAddIFieldsX4_VectorAPI(oops, mem); } From c87ecaddfb32485b2ecaecc9284ce37b610ffffc Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Thu, 5 Mar 2026 09:23:21 +0000 Subject: [PATCH 065/170] 8379192: Use an initializer list in the ObjectWaiter constructor Reviewed-by: coleenp, dholmes, aartemov --- src/hotspot/share/runtime/objectMonitor.cpp | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 8c6994c2152..91771772e2c 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -2541,19 +2541,19 @@ bool ObjectMonitor::try_spin(JavaThread* current) { // ----------------------------------------------------------------------------- // wait_set management ... -ObjectWaiter::ObjectWaiter(JavaThread* current) { - _next = nullptr; - _prev = nullptr; - _thread = current; - _monitor = nullptr; - _notifier_tid = 0; - _recursions = 0; - TState = TS_RUN; - _is_wait = false; - _at_reenter = false; - _interrupted = false; - _do_timed_park = false; - _active = false; +ObjectWaiter::ObjectWaiter(JavaThread* current) + : _next(nullptr), + _prev(nullptr), + _thread(current), + _monitor(nullptr), + _notifier_tid(0), + _recursions(0), + TState(TS_RUN), + _is_wait(false), + _at_reenter(false), + _interrupted(false), + _do_timed_park(false), + _active(false) { } const char* ObjectWaiter::getTStateName(ObjectWaiter::TStates state) { From 28e8700f461cee6c80da15c71090eaf608b6f8fa Mon Sep 17 00:00:00 2001 From: David Briemann Date: Thu, 5 Mar 2026 10:08:57 +0000 Subject: [PATCH 066/170] 8378675: PPC64: increase instruction cache line size Reviewed-by: mdoerr --- src/hotspot/cpu/ppc/icache_ppc.cpp | 8 +++- src/hotspot/cpu/ppc/icache_ppc.hpp | 9 ++-- src/hotspot/cpu/ppc/vm_version_ppc.cpp | 39 +++++----------- src/hotspot/cpu/ppc/vm_version_ppc.hpp | 7 ++- .../os_cpu/aix_ppc/vm_version_aix_ppc.cpp | 36 +++++++++++++++ .../os_cpu/linux_ppc/vm_version_linux_ppc.cpp | 44 +++++++++++++++++++ 6 files changed, 105 insertions(+), 38 deletions(-) create mode 100644 src/hotspot/os_cpu/aix_ppc/vm_version_aix_ppc.cpp create mode 100644 src/hotspot/os_cpu/linux_ppc/vm_version_linux_ppc.cpp diff --git a/src/hotspot/cpu/ppc/icache_ppc.cpp b/src/hotspot/cpu/ppc/icache_ppc.cpp index 05ad3c7a30d..f3d51bad18c 100644 --- a/src/hotspot/cpu/ppc/icache_ppc.cpp +++ b/src/hotspot/cpu/ppc/icache_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ */ #include "runtime/icache.hpp" +#include "runtime/vm_version.hpp" // Use inline assembler to implement icache flush. int ICache::ppc64_flush_icache(address start, int lines, int magic) { @@ -67,6 +68,9 @@ int ICache::ppc64_flush_icache(address start, int lines, int magic) { void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) { + guarantee(VM_Version::get_icache_line_size() >= ICache::line_size, + "processors with smaller cache line size are no longer supported"); + *flush_icache_stub = (ICache::flush_icache_stub_t)ICache::ppc64_flush_icache; // First call to flush itself. diff --git a/src/hotspot/cpu/ppc/icache_ppc.hpp b/src/hotspot/cpu/ppc/icache_ppc.hpp index d348cad1c72..024f706182a 100644 --- a/src/hotspot/cpu/ppc/icache_ppc.hpp +++ b/src/hotspot/cpu/ppc/icache_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,9 +35,8 @@ class ICache : public AbstractICache { public: enum { - // Actually, cache line size is 64, but keeping it as it is to be - // on the safe side on ALL PPC64 implementations. - log2_line_size = 5, + // Cache line size is 128 on all supported PPC64 implementations. + log2_line_size = 7, line_size = 1 << log2_line_size }; diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 75feb389298..e471f5a6e4f 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -475,19 +475,12 @@ void VM_Version::print_features() { void VM_Version::determine_features() { #if defined(ABI_ELFv2) - // 1 InstWord per call for the blr instruction. - const int code_size = (num_features+1+2*1)*BytesPerInstWord; + const int code_size = (num_features + 1 /*blr*/) * BytesPerInstWord; #else - // 7 InstWords for each call (function descriptor + blr instruction). - const int code_size = (num_features+1+2*7)*BytesPerInstWord; + const int code_size = (num_features + 1 /*blr*/ + 6 /* fd */) * BytesPerInstWord; #endif int features = 0; - // create test area - enum { BUFFER_SIZE = 2*4*K }; // Needs to be >=2* max cache line size (cache line size can't exceed min page size). - char test_area[BUFFER_SIZE]; - char *mid_of_test_area = &test_area[BUFFER_SIZE>>1]; - // Allocate space for the code. ResourceMark rm; CodeBuffer cb("detect_cpu_features", code_size, 0); @@ -497,20 +490,13 @@ void VM_Version::determine_features() { _features = VM_Version::all_features_m; // Emit code. - void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->function_entry(); + void (*test)() = (void(*)())(void *)a->function_entry(); uint32_t *code = (uint32_t *)a->pc(); - // Keep R3_ARG1 unmodified, it contains &field (see below). - // Keep R4_ARG2 unmodified, it contains offset = 0 (see below). a->mfdscr(R0); a->darn(R7); a->brw(R5, R6); a->blr(); - // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it. - void (*zero_cacheline_func_ptr)(char*) = (void(*)(char*))(void *)a->function_entry(); - a->dcbz(R3_ARG1); // R3_ARG1 = addr - a->blr(); - uint32_t *code_end = (uint32_t *)a->pc(); a->flush(); _features = VM_Version::unknown_m; @@ -522,18 +508,9 @@ void VM_Version::determine_features() { Disassembler::decode((u_char*)code, (u_char*)code_end, tty); } - // Measure cache line size. - memset(test_area, 0xFF, BUFFER_SIZE); // Fill test area with 0xFF. - (*zero_cacheline_func_ptr)(mid_of_test_area); // Call function which executes dcbz to the middle. - int count = 0; // count zeroed bytes - for (int i = 0; i < BUFFER_SIZE; i++) if (test_area[i] == 0) count++; - guarantee(is_power_of_2(count), "cache line size needs to be a power of 2"); - _L1_data_cache_line_size = count; - // Execute code. Illegal instructions will be replaced by 0 in the signal handler. VM_Version::_is_determine_features_test_running = true; - // We must align the first argument to 16 bytes because of the lqarx check. - (*test)(align_up((address)mid_of_test_area, 16), 0); + (*test)(); VM_Version::_is_determine_features_test_running = false; // determine which instructions are legal. @@ -550,6 +527,10 @@ void VM_Version::determine_features() { } _features = features; + + _L1_data_cache_line_size = VM_Version::get_dcache_line_size(); + assert(_L1_data_cache_line_size >= DEFAULT_CACHE_LINE_SIZE, + "processors with smaller cache line size are no longer supported"); } // Power 8: Configure Data Stream Control Register. diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index 11dce83bed0..0f4eb3593a3 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,6 +81,9 @@ public: static uint64_t _dscr_val; static void initialize_cpu_information(void); + + static int get_dcache_line_size(); + static int get_icache_line_size(); }; #endif // CPU_PPC_VM_VERSION_PPC_HPP diff --git a/src/hotspot/os_cpu/aix_ppc/vm_version_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/vm_version_aix_ppc.cpp new file mode 100644 index 00000000000..8cc8b715201 --- /dev/null +++ b/src/hotspot/os_cpu/aix_ppc/vm_version_aix_ppc.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "runtime/vm_version.hpp" + +#include + +int VM_Version::get_dcache_line_size() { + return _system_configuration.dcache_line; +} + +int VM_Version::get_icache_line_size() { + return _system_configuration.icache_line; +} diff --git a/src/hotspot/os_cpu/linux_ppc/vm_version_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/vm_version_linux_ppc.cpp new file mode 100644 index 00000000000..d64340edf5c --- /dev/null +++ b/src/hotspot/os_cpu/linux_ppc/vm_version_linux_ppc.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "runtime/vm_version.hpp" + +#include + +int VM_Version::get_dcache_line_size() { + // This should work on all modern linux versions: + int size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); + // It may fail with very old linux / glibc versions. We use DEFAULT_CACHE_LINE_SIZE in this case. + // That is the correct value for all currently supported processors. + return (size <= 0) ? DEFAULT_CACHE_LINE_SIZE : size; +} + +int VM_Version::get_icache_line_size() { + // This should work on all modern linux versions: + int size = sysconf(_SC_LEVEL1_ICACHE_LINESIZE); + // It may fail with very old linux / glibc versions. We use DEFAULT_CACHE_LINE_SIZE in this case. + // That is the correct value for all currently supported processors. + return (size <= 0) ? DEFAULT_CACHE_LINE_SIZE : size; +} From c9a0e365083a7868c49f082623d722e721838642 Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Thu, 5 Mar 2026 10:13:26 +0000 Subject: [PATCH 067/170] 8378376: DaCapo-h2-large regression after JDK-8238686 Reviewed-by: kbarrett, tschatzl --- src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp | 8 +++++++- src/hotspot/share/gc/shared/collectedHeap.hpp | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp index 4dd0a509bcd..1b9704e8ad3 100644 --- a/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp +++ b/src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -366,6 +366,12 @@ static size_t target_heap_capacity(size_t used_bytes, uintx free_ratio) { } size_t G1HeapSizingPolicy::full_collection_resize_amount(bool& expand, size_t allocation_word_size) { + // User-requested Full GCs introduce GC load unrelated to heap size; reset CPU + // usage tracking so heap resizing heuristics are driven only by GC pressure. + if (GCCause::is_user_requested_gc(_g1h->gc_cause())) { + reset_cpu_usage_tracking_data(); + } + const size_t capacity_after_gc = _g1h->capacity(); // Capacity, free and used after the GC counted as full regions to // include the waste in the following calculations. diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index f13c3ab7b6e..100866bb528 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -289,7 +289,7 @@ protected: DEBUG_ONLY(bool is_in_or_null(const void* p) const { return p == nullptr || is_in(p); }) void set_gc_cause(GCCause::Cause v); - GCCause::Cause gc_cause() { return _gc_cause; } + GCCause::Cause gc_cause() const { return _gc_cause; } oop obj_allocate(Klass* klass, size_t size, TRAPS); virtual oop array_allocate(Klass* klass, size_t size, int length, bool do_zero, TRAPS); From ec3b58b5e0c93c9e32a59dd1b65bd3b9dea6e12b Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Thu, 5 Mar 2026 10:37:23 +0000 Subject: [PATCH 068/170] 8379162: AggregateRequestBodyTest.java intermittent fails "Connection closed by client peer: APPLICATION_ERROR" Reviewed-by: jpai, syan, djelinski --- .../httpclient/AggregateRequestBodyTest.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java b/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java index 175e860c229..fb67cf02566 100644 --- a/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java +++ b/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java @@ -74,6 +74,7 @@ import static java.lang.System.out; import static java.net.http.HttpClient.Version.HTTP_1_1; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Version.HTTP_3; +import static java.net.http.HttpOption.H3_DISCOVERY; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import org.junit.jupiter.api.AfterAll; @@ -81,7 +82,6 @@ import org.junit.jupiter.api.Assertions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; @@ -219,7 +219,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { int i = 0; for (boolean sameClient : List.of(false, true)) { for (URI uri : uris()) { - HttpClient.Version version = null; + final HttpClient.Version version; if (uri.equals(http1URI) || uri.equals(https1URI)) version = HttpClient.Version.HTTP_1_1; else if (uri.equals(http2URI) || uri.equals(https2URI)) version = HttpClient.Version.HTTP_2; else if (uri.equals(http3URI)) version = HTTP_3; @@ -295,7 +295,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { static List lengths(long... lengths) { return LongStream.of(lengths) - .mapToObj(Long::valueOf) + .boxed() .collect(Collectors.toList()); } @@ -446,7 +446,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { @Override public void onComplete() { - resultCF.complete(items.stream().collect(Collectors.toUnmodifiableList())); + resultCF.complete(items.stream().toList()); } public ByteBuffer take() { @@ -552,7 +552,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { subscriber.subscriptionCF.thenAccept(s -> s.request(Long.MAX_VALUE)); if (errorPublisher.hasErrors()) { CompletionException ce = Assertions.assertThrows(CompletionException.class, - () -> subscriber.resultCF.join()); + subscriber.resultCF::join); out.println(description + ": got expected " + ce); assertEquals(Exception.class, ce.getCause().getClass()); assertEquals(result, stringFromBytes(subscriber.items.stream()) + ""); @@ -600,7 +600,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { description.replace("null", "length(-1)")); } - private static final Throwable completionCause(CompletionException x) { + private static Throwable completionCause(CompletionException x) { while (x.getCause() instanceof CompletionException) { x = (CompletionException)x.getCause(); } @@ -618,7 +618,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { publisher.subscribe(subscriber); Subscription subscription = subscriber.subscriptionCF.join(); subscription.request(n); - CompletionException expected = Assertions.assertThrows(CE, () -> subscriber.resultCF.join()); + CompletionException expected = Assertions.assertThrows(CE, subscriber.resultCF::join); Throwable cause = completionCause(expected); if (cause instanceof IllegalArgumentException) { System.out.printf("Got expected IAE for %d: %s%n", n, cause); @@ -655,7 +655,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { assertTrue(requestSubscriber1.resultCF().isDone()); String result1 = stringFromBytes(list1.stream()); assertEquals("Lorem ipsum dolor sit amet, consectetur adipiscing elit.", result1); - System.out.println("Got expected sentence with one request: \"%s\"".formatted(result1)); + System.out.printf("Got expected sentence with one request: \"%s\"%n", result1); // Test that we can split our requests call any which way we want // (whether in the 'middle of a publisher' or at the boundaries. @@ -824,7 +824,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { .toArray(HttpRequest.BodyPublisher[]::new) ); - HttpRequest request = HttpRequest.newBuilder(uri) + HttpRequest request = newRequestBuilder(uri) .version(version) .POST(publisher) .build(); @@ -835,13 +835,21 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { HttpResponse response = client.send(request, BodyHandlers.ofString()); int expectedResponse = RESPONSE_CODE; if (response.statusCode() != expectedResponse) - throw new RuntimeException("wrong response code " + Integer.toString(response.statusCode())); + throw new RuntimeException("wrong response code " + response.statusCode()); assertEquals(BODIES.stream().collect(Collectors.joining()), response.body()); } if (!sameClient) client.close(); System.out.println("test: DONE"); } + private static HttpRequest.Builder newRequestBuilder(URI uri) { + var builder = HttpRequest.newBuilder(uri); + if (uri.getPath().contains("/http3/")) { + builder.setOption(H3_DISCOVERY, HTTP_3_URI_ONLY); + } + return builder; + } + private static URI buildURI(String scheme, String path, int port) { return URIBuilder.newBuilder() .scheme(scheme) @@ -882,11 +890,17 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { http3TestServer.start(); } + private static void close(AutoCloseable closeable) throws Exception { + if (closeable == null) return; + out.println("Closing shared client " + closeable); + closeable.close(); + } + @AfterAll public static void teardown() throws Exception { String sharedClientName = sharedClient == null ? null : sharedClient.toString(); - sharedClient.close(); + close(sharedClient); sharedClient = null; Thread.sleep(100); AssertionError fail = TRACKER.check(500); From 8a9b63f76fd678c6883a51332aeb84846791ed5e Mon Sep 17 00:00:00 2001 From: Kerem Kat Date: Thu, 5 Mar 2026 11:05:01 +0000 Subject: [PATCH 069/170] 8378413: C2: Missed Ideal optimization opportunity in PhaseIterGVN for URShiftI still exists Reviewed-by: qamai, dlong --- src/hotspot/share/opto/mulnode.cpp | 18 ++- .../c2/gvn/MissedURShiftIAddILShiftIdeal.java | 134 ++++++++++++++++++ 2 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 9bdaa3b9f34..cac9f1dcc37 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -1539,15 +1539,20 @@ Node* URShiftINode::Ideal(PhaseGVN* phase, bool can_reshape) { Node *add = in(1); if (in1_op == Op_AddI) { Node *lshl = add->in(1); + Node *y = add->in(2); + if (lshl->Opcode() != Op_LShiftI) { + lshl = add->in(2); + y = add->in(1); + } // Compare shift counts by value, not by node pointer, to also match a not-yet-normalized // negative constant (e.g. -1 vs 31) int lshl_con = 0; if (lshl->Opcode() == Op_LShiftI && const_shift_count(phase, lshl, &lshl_con) && (lshl_con & (BitsPerJavaInteger - 1)) == con) { - Node *y_z = phase->transform( new URShiftINode(add->in(2),in(2)) ); - Node *sum = phase->transform( new AddINode( lshl->in(1), y_z ) ); - return new AndINode( sum, phase->intcon(mask) ); + Node *y_z = phase->transform(new URShiftINode(y, in(2))); + Node *sum = phase->transform(new AddINode(lshl->in(1), y_z)); + return new AndINode(sum, phase->intcon(mask)); } } @@ -1699,13 +1704,18 @@ Node* URShiftLNode::Ideal(PhaseGVN* phase, bool can_reshape) { const TypeInt *t2 = phase->type(in(2))->isa_int(); if (add->Opcode() == Op_AddL) { Node *lshl = add->in(1); + Node *y = add->in(2); + if (lshl->Opcode() != Op_LShiftL) { + lshl = add->in(2); + y = add->in(1); + } // Compare shift counts by value, not by node pointer, to also match a not-yet-normalized // negative constant (e.g. -1 vs 63) int lshl_con = 0; if (lshl->Opcode() == Op_LShiftL && const_shift_count(phase, lshl, &lshl_con) && (lshl_con & (BitsPerJavaLong - 1)) == con) { - Node* y_z = phase->transform(new URShiftLNode(add->in(2), in(2))); + Node* y_z = phase->transform(new URShiftLNode(y, in(2))); Node* sum = phase->transform(new AddLNode(lshl->in(1), y_z)); return new AndLNode(sum, phase->longcon(mask)); } diff --git a/test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java b/test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java new file mode 100644 index 00000000000..a1f4f011466 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package compiler.c2.gvn; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import java.util.Random; + +/* + * @test + * @bug 8378413 + * @key randomness + * @summary Verify that URShift{I,L}Node::Ideal optimizes ((x << C) + y) >>> C + * regardless of Add input order, i.e. it is commutative w.r.t. the addition. + * @library /test/lib / + * @run driver ${test.main.class} + * @run driver ${test.main.class} -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:VerifyIterativeGVN=1110 -Xbatch -XX:CompileCommand=compileonly,${test.main.class}::* + */ +public class MissedURShiftIAddILShiftIdeal { + + private static final Random RANDOM = Utils.getRandomInstance(); + + public static void main(String[] args) { + TestFramework.run(); + } + + @Run(test = {"testI", "testICommuted", "testIComputedY", + "testL", "testLCommuted", "testLComputedY"}) + public void runMethod() { + int xi = RANDOM.nextInt(); + int yi = RANDOM.nextInt(); + int ai = RANDOM.nextInt(); + int bi = RANDOM.nextInt(); + long xl = RANDOM.nextLong(); + long yl = RANDOM.nextLong(); + long al = RANDOM.nextLong(); + long bl = RANDOM.nextLong(); + + assertResultI(xi, yi, ai, bi); + assertResultL(xl, yl, al, bl); + } + + @DontCompile + public void assertResultI(int x, int y, int a, int b) { + Asserts.assertEQ(((x << 3) + y) >>> 3, testI(x, y)); + Asserts.assertEQ((y + (x << 5)) >>> 5, testICommuted(x, y)); + Asserts.assertEQ(((x << 7) + (a ^ b)) >>> 7, testIComputedY(x, a, b)); + } + + @DontCompile + public void assertResultL(long x, long y, long a, long b) { + Asserts.assertEQ(((x << 9) + y) >>> 9, testL(x, y)); + Asserts.assertEQ((y + (x << 11)) >>> 11, testLCommuted(x, y)); + Asserts.assertEQ(((x << 13) + (a ^ b)) >>> 13, testLComputedY(x, a, b)); + } + + @Test + // ((x << 3) + y) >>> 3 => (x + (y >>> 3)) & mask + @IR(counts = {IRNode.LSHIFT_I, "0", + IRNode.URSHIFT_I, "1", + IRNode.AND_I, "1"}) + static int testI(int x, int y) { + return ((x << 3) + y) >>> 3; + } + + @Test + // (y + (x << 5)) >>> 5 => (x + (y >>> 5)) & mask (commuted Add) + @IR(counts = {IRNode.LSHIFT_I, "0", + IRNode.URSHIFT_I, "1", + IRNode.AND_I, "1"}) + static int testICommuted(int x, int y) { + return (y + (x << 5)) >>> 5; + } + + @Test + // ((x << 7) + (a ^ b)) >>> 7 => (x + ((a ^ b) >>> 7)) & mask + // Computed y (a ^ b) has higher _idx than LShift, so LShift stays in Add's in(1). + @IR(counts = {IRNode.LSHIFT_I, "0", + IRNode.URSHIFT_I, "1", + IRNode.AND_I, "1"}) + static int testIComputedY(int x, int a, int b) { + return ((x << 7) + (a ^ b)) >>> 7; + } + + @Test + // ((x << 9) + y) >>> 9 => (x + (y >>> 9)) & mask + @IR(counts = {IRNode.LSHIFT_L, "0", + IRNode.URSHIFT_L, "1", + IRNode.AND_L, "1"}) + static long testL(long x, long y) { + return ((x << 9) + y) >>> 9; + } + + @Test + // (y + (x << 11)) >>> 11 => (x + (y >>> 11)) & mask (commuted Add) + @IR(counts = {IRNode.LSHIFT_L, "0", + IRNode.URSHIFT_L, "1", + IRNode.AND_L, "1"}) + static long testLCommuted(long x, long y) { + return (y + (x << 11)) >>> 11; + } + + @Test + // ((x << 13) + (a ^ b)) >>> 13 => (x + ((a ^ b) >>> 13)) & mask + // Computed y (a ^ b) has higher _idx than LShift, so LShift stays in Add's in(1). + @IR(counts = {IRNode.LSHIFT_L, "0", + IRNode.URSHIFT_L, "1", + IRNode.AND_L, "1"}) + static long testLComputedY(long x, long a, long b) { + return ((x << 13) + (a ^ b)) >>> 13; + } +} From 97b78f04230452b675a31d8e37f300a2d31e62ed Mon Sep 17 00:00:00 2001 From: Eric Fang Date: Thu, 5 Mar 2026 11:12:08 +0000 Subject: [PATCH 070/170] 8374349: [VectorAPI]: AArch64: Prefer merging mode SVE CPY instruction Reviewed-by: aph --- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 8 +++---- .../cpu/aarch64/c2_MacroAssembler_aarch64.cpp | 21 +++++++++++++++++++ .../cpu/aarch64/c2_MacroAssembler_aarch64.hpp | 5 +++++ .../cpu/aarch64/vm_version_aarch64.hpp | 5 +++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 19b3bb1a65b..67cf77989d2 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -3814,8 +3814,8 @@ public: } private: - void sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, int imm8, - bool isMerge, bool isFloat) { + void _sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, int imm8, + bool isMerge, bool isFloat) { starti; assert(T != Q, "invalid size"); int sh = 0; @@ -3839,11 +3839,11 @@ private: public: // SVE copy signed integer immediate to vector elements (predicated) void sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, int imm8, bool isMerge) { - sve_cpy(Zd, T, Pg, imm8, isMerge, /*isFloat*/false); + _sve_cpy(Zd, T, Pg, imm8, isMerge, /*isFloat*/false); } // SVE copy floating-point immediate to vector elements (predicated) void sve_cpy(FloatRegister Zd, SIMD_RegVariant T, PRegister Pg, double d) { - sve_cpy(Zd, T, Pg, checked_cast(pack(d)), /*isMerge*/true, /*isFloat*/true); + _sve_cpy(Zd, T, Pg, checked_cast(pack(d)), /*isMerge*/true, /*isFloat*/true); } // SVE conditionally select elements from two vectors diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index dc0b9eb9546..7aab7d389e1 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -2875,3 +2875,24 @@ void C2_MacroAssembler::vector_expand_sve(FloatRegister dst, FloatRegister src, // dst = 00 87 00 65 00 43 00 21 sve_tbl(dst, size, src, dst); } + +// Optimized SVE cpy (imm, zeroing) instruction. +// +// `movi; cpy(imm, merging)` and `cpy(imm, zeroing)` have the same +// functionality, but test results show that `movi; cpy(imm, merging)` has +// higher throughput on some microarchitectures. This would depend on +// microarchitecture and so may vary between implementations. +void C2_MacroAssembler::sve_cpy(FloatRegister dst, SIMD_RegVariant T, + PRegister pg, int imm8, bool isMerge) { + if (VM_Version::prefer_sve_merging_mode_cpy() && !isMerge) { + // Generates a NEON instruction `movi V.2d, #0`. + // On AArch64, Z and V registers alias in the low 128 bits, so V is + // the low 128 bits of Z. A write to V also clears all bits of + // Z above 128, so this `movi` instruction effectively zeroes the + // entire Z register. According to the Arm Software Optimization + // Guide, `movi` is zero latency. + movi(dst, T2D, 0); + isMerge = true; + } + Assembler::sve_cpy(dst, T, pg, imm8, isMerge); +} diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp index 4f3a41da402..5c05832afbe 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp @@ -75,6 +75,8 @@ unsigned vector_length_in_bytes); public: + using Assembler::sve_cpy; + // jdk.internal.util.ArraysSupport.vectorizedHashCode address arrays_hashcode(Register ary, Register cnt, Register result, FloatRegister vdata0, FloatRegister vdata1, FloatRegister vdata2, FloatRegister vdata3, @@ -244,4 +246,7 @@ void vector_expand_sve(FloatRegister dst, FloatRegister src, PRegister pg, FloatRegister tmp1, FloatRegister tmp2, BasicType bt, int vector_length_in_bytes); + + void sve_cpy(FloatRegister dst, SIMD_RegVariant T, PRegister pg, int imm8, + bool isMerge); #endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 0213872852b..e8681611234 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -55,6 +55,9 @@ protected: static int _max_supported_sve_vector_length; static bool _rop_protection; static uintptr_t _pac_mask; + // When _prefer_sve_merging_mode_cpy is true, `cpy (imm, zeroing)` is + // implemented as `movi; cpy(imm, merging)`. + static constexpr bool _prefer_sve_merging_mode_cpy = true; static SpinWait _spin_wait; @@ -242,6 +245,8 @@ public: static bool use_rop_protection() { return _rop_protection; } + static bool prefer_sve_merging_mode_cpy() { return _prefer_sve_merging_mode_cpy; } + // For common 64/128-bit unpredicated vector operations, we may prefer // emitting NEON instructions rather than the corresponding SVE instructions. static bool use_neon_for_vector(int vector_length_in_bytes) { From fc77e3e9a2bedd3cefc98ca28516eb85ceefe2e5 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Thu, 5 Mar 2026 11:12:33 +0000 Subject: [PATCH 071/170] 8378599: Refactor tests under test/jdk/java/net/httpclient/whitebox from TestNG to JUnit Reviewed-by: vyazici, syan --- .../httpclient/whitebox/AltSvcFrameTest.java | 36 +++--- .../whitebox/AltSvcRegistryTest.java | 21 +-- .../AuthenticationFilterTestDriver.java | 4 +- .../whitebox/DefaultProxyDriver.java | 4 +- .../httpclient/whitebox/DemandTestDriver.java | 4 +- .../httpclient/whitebox/FlowTestDriver.java | 4 +- .../whitebox/FramesDecoderTestDriver.java | 4 +- .../whitebox/Http1HeaderParserTestDriver.java | 4 +- .../whitebox/MinimalFutureTestDriver.java | 4 +- .../whitebox/RawChannelTestDriver.java | 6 +- .../whitebox/SSLEchoTubeTestDriver.java | 4 +- .../whitebox/SSLFlowDelegateTestDriver.java | 4 +- .../whitebox/SSLTubeTestDriver.java | 4 +- .../whitebox/SelectorTestDriver.java | 4 +- .../whitebox/WindowControllerTestDriver.java | 4 +- .../whitebox/WrapperTestDriver.java | 4 +- .../net/http/AbstractSSLTubeTest.java | 6 +- .../net/http/AuthenticationFilterTest.java | 61 ++++----- .../jdk/internal/net/http/DefaultProxy.java | 33 ++--- .../jdk/internal/net/http/FlowTest.java | 16 +-- .../net/http/Http1HeaderParserTest.java | 47 +++---- .../jdk/internal/net/http/RawChannelTest.java | 11 +- .../internal/net/http/SSLEchoTubeTest.java | 6 +- .../net/http/SSLFlowDelegateTest.java | 75 +++++------ .../jdk/internal/net/http/SSLTubeTest.java | 14 +- .../jdk/internal/net/http/SelectorTest.java | 6 +- .../net/http/WindowControllerTest.java | 121 +++++++++--------- .../jdk/internal/net/http/WrapperTest.java | 7 +- .../internal/net/http/common/DemandTest.java | 63 +++++---- .../net/http/common/MinimalFutureTest.java | 15 +-- .../net/http/frame/FramesDecoderTest.java | 32 ++--- 31 files changed, 324 insertions(+), 304 deletions(-) diff --git a/test/jdk/java/net/httpclient/whitebox/AltSvcFrameTest.java b/test/jdk/java/net/httpclient/whitebox/AltSvcFrameTest.java index 589e5409044..b9e5f2d58fe 100644 --- a/test/jdk/java/net/httpclient/whitebox/AltSvcFrameTest.java +++ b/test/jdk/java/net/httpclient/whitebox/AltSvcFrameTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,17 +48,19 @@ import jdk.internal.net.http.HttpClientAccess; import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.frame.AltSvcFrame; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.net.http.HttpResponse.BodyHandlers.ofString; import static jdk.internal.net.http.AltServicesRegistry.AltService; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test - * @summary This test verifies alt-svc registry updation for frames + * @summary This test verifies alt-svc registry updating for frames * @library /test/lib /test/jdk/java/net/httpclient/lib * @build java.net.http/jdk.internal.net.http.HttpClientAccess * jdk.httpclient.test.lib.http2.Http2TestServer @@ -82,7 +84,7 @@ import static org.testng.Assert.assertTrue; * java.base/sun.net.www.http * java.base/sun.net.www * java.base/sun.net - * @run testng/othervm + * @run junit/othervm * -Dtest.requiresHost=true * -Djdk.httpclient.HttpClient.log=headers * -Djdk.internal.httpclient.disableHostnameVerification @@ -90,7 +92,6 @@ import static org.testng.Assert.assertTrue; * AltSvcFrameTest */ - public class AltSvcFrameTest { private static final String IGNORED_HOST = "www.should-be-ignored.com"; @@ -109,18 +110,23 @@ public class AltSvcFrameTest { static HttpClient client; private static final SSLContext server = SimpleSSLContext.findSSLContext(); - @BeforeTest - public void setUp() throws Exception { + @BeforeAll + public static void setUp() throws Exception { getRegistry(); https2Server = new Http2TestServer("localhost", true, server); https2Server.addHandler(new AltSvcFrameTestHandler(), "/"); https2Server.setExchangeSupplier(AltSvcFrameTest.CFTHttp2TestExchange::new); https2Server.start(); https2URI = "https://" + https2Server.serverAuthority() + "/"; - - } + @AfterAll + public static void tearDown() { + if (client != null) client.close(); + if (https2Server != null) https2Server.stop(); + } + + static AltServicesRegistry getRegistry() { client = HttpClient.newBuilder() .sslContext(server) @@ -139,7 +145,7 @@ public class AltSvcFrameTest { .GET() .build(); HttpResponse response = client.send(request, ofString()); - assertEquals(response.statusCode(), 200, "unexpected response code"); + assertEquals(200, response.statusCode(), "unexpected response code"); final List services = registry.lookup(URI.create(https2URI), "h3").toList(); System.out.println("Alt services in registry for " + https2URI + " = " + services); final boolean hasExpectedAltSvc = services.stream().anyMatch( @@ -158,7 +164,7 @@ public class AltSvcFrameTest { .GET() .build(); HttpResponse response = client.send(request, ofString()); - assertEquals(response.statusCode(), 200, "unexpected response code"); + assertEquals(200, response.statusCode(), "unexpected response code"); final List services = registry.lookup( URI.create(FOO_BAR_ORIGIN), "h3").toList(); System.out.println("Alt services in registry for " + FOO_BAR_ORIGIN + " = " + services); diff --git a/test/jdk/java/net/httpclient/whitebox/AltSvcRegistryTest.java b/test/jdk/java/net/httpclient/whitebox/AltSvcRegistryTest.java index b853f715415..682082ba9f8 100644 --- a/test/jdk/java/net/httpclient/whitebox/AltSvcRegistryTest.java +++ b/test/jdk/java/net/httpclient/whitebox/AltSvcRegistryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ import jdk.internal.net.http.AltServicesRegistry; import jdk.test.lib.net.SimpleSSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -46,6 +44,10 @@ import java.util.concurrent.Executors; import static jdk.internal.net.http.AltServicesRegistry.AltService; import static java.net.http.HttpResponse.BodyHandlers.ofString; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + /* * @test * @summary This test verifies alt-svc registry updates @@ -73,7 +75,7 @@ import static java.net.http.HttpResponse.BodyHandlers.ofString; * java.base/sun.net.www * java.base/sun.net * java.base/jdk.internal.util - * @run testng/othervm + * @run junit/othervm * -Dtest.requiresHost=true * -Djdk.httpclient.HttpClient.log=headers * -Djdk.internal.httpclient.disableHostnameVerification @@ -81,7 +83,6 @@ import static java.net.http.HttpResponse.BodyHandlers.ofString; * AltSvcRegistryTest */ - public class AltSvcRegistryTest implements HttpServerAdapters { static HttpTestServer https2Server; @@ -89,8 +90,8 @@ public class AltSvcRegistryTest implements HttpServerAdapters { static HttpClient client; private static final SSLContext server = SimpleSSLContext.findSSLContext(); - @BeforeTest - public void setUp() throws Exception { + @BeforeAll + public static void setUp() throws Exception { getRegistry(); final ExecutorService executor = Executors.newCachedThreadPool(); https2Server = HttpServerAdapters.HttpTestServer.of( @@ -98,8 +99,12 @@ public class AltSvcRegistryTest implements HttpServerAdapters { https2Server.addHandler(new AltSvcRegistryTestHandler("https", https2Server), "/"); https2Server.start(); https2URI = "https://" + https2Server.serverAuthority() + "/"; + } - + @AfterAll + public static void tearDown() { + if (client != null) client.close(); + if (https2Server != null) https2Server.stop(); } static AltServicesRegistry getRegistry() { diff --git a/test/jdk/java/net/httpclient/whitebox/AuthenticationFilterTestDriver.java b/test/jdk/java/net/httpclient/whitebox/AuthenticationFilterTestDriver.java index e932455e409..5808c380593 100644 --- a/test/jdk/java/net/httpclient/whitebox/AuthenticationFilterTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/AuthenticationFilterTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,5 +24,5 @@ /* * @test * @modules java.net.http/jdk.internal.net.http - * @run testng java.net.http/jdk.internal.net.http.AuthenticationFilterTest + * @run junit java.net.http/jdk.internal.net.http.AuthenticationFilterTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/DefaultProxyDriver.java b/test/jdk/java/net/httpclient/whitebox/DefaultProxyDriver.java index 5c18fd84a0f..54127855386 100644 --- a/test/jdk/java/net/httpclient/whitebox/DefaultProxyDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/DefaultProxyDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @summary Verifies that the HTTP Client, by default, uses the system-wide * proxy selector, and that that selector supports the standard HTTP proxy * system properties. - * @run testng/othervm + * @run junit/othervm * -Dhttp.proxyHost=foo.proxy.com * -Dhttp.proxyPort=9876 * -Dhttp.nonProxyHosts=*.direct.com diff --git a/test/jdk/java/net/httpclient/whitebox/DemandTestDriver.java b/test/jdk/java/net/httpclient/whitebox/DemandTestDriver.java index ea442878261..c8b793a289c 100644 --- a/test/jdk/java/net/httpclient/whitebox/DemandTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/DemandTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,5 +24,5 @@ /* * @test * @modules java.net.http/jdk.internal.net.http.common - * @run testng java.net.http/jdk.internal.net.http.common.DemandTest + * @run junit java.net.http/jdk.internal.net.http.common.DemandTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/FlowTestDriver.java b/test/jdk/java/net/httpclient/whitebox/FlowTestDriver.java index c24a733db3b..4468b5d6eb6 100644 --- a/test/jdk/java/net/httpclient/whitebox/FlowTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/FlowTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,5 +25,5 @@ * @test * @compile/module=java.net.http ../../../../../../lib/jdk/test/lib/net/SimpleSSLContext.java * @modules java.net.http/jdk.internal.net.http - * @run testng/timeout=480 java.net.http/jdk.internal.net.http.FlowTest + * @run junit/timeout=480 java.net.http/jdk.internal.net.http.FlowTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/FramesDecoderTestDriver.java b/test/jdk/java/net/httpclient/whitebox/FramesDecoderTestDriver.java index 9b3c8878669..7edc555d8a6 100644 --- a/test/jdk/java/net/httpclient/whitebox/FramesDecoderTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/FramesDecoderTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8195823 * @modules java.net.http/jdk.internal.net.http.frame - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * java.net.http/jdk.internal.net.http.frame.FramesDecoderTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/Http1HeaderParserTestDriver.java b/test/jdk/java/net/httpclient/whitebox/Http1HeaderParserTestDriver.java index b18142601a5..f3b9d410b51 100644 --- a/test/jdk/java/net/httpclient/whitebox/Http1HeaderParserTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/Http1HeaderParserTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,5 +25,5 @@ * @test * @bug 8195138 * @modules java.net.http/jdk.internal.net.http - * @run testng java.net.http/jdk.internal.net.http.Http1HeaderParserTest + * @run junit java.net.http/jdk.internal.net.http.Http1HeaderParserTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/MinimalFutureTestDriver.java b/test/jdk/java/net/httpclient/whitebox/MinimalFutureTestDriver.java index 316ca29e2a6..90fe6816adc 100644 --- a/test/jdk/java/net/httpclient/whitebox/MinimalFutureTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/MinimalFutureTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,5 +24,5 @@ /* * @test * @modules java.net.http/jdk.internal.net.http.common - * @run testng java.net.http/jdk.internal.net.http.common.MinimalFutureTest + * @run junit java.net.http/jdk.internal.net.http.common.MinimalFutureTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java b/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java index ab44fba5ecd..7ca448b7892 100644 --- a/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/RawChannelTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,10 @@ * @test * @bug 8151299 8164704 * @modules java.net.http/jdk.internal.net.http - * @run testng/othervm java.net.http/jdk.internal.net.http.RawChannelTest + * @run junit/othervm java.net.http/jdk.internal.net.http.RawChannelTest */ // use -// @run testng/othervm -Dseed=6434511950803022575 +// @run junit/othervm -Dseed=6434511950803022575 // java.net.http/jdk.internal.net.http.RawChannelTest // to reproduce a failure with a particular seed (e.g. 6434511950803022575) // if this test is observed failing with that seed diff --git a/test/jdk/java/net/httpclient/whitebox/SSLEchoTubeTestDriver.java b/test/jdk/java/net/httpclient/whitebox/SSLEchoTubeTestDriver.java index d641513b298..b4b3e59326d 100644 --- a/test/jdk/java/net/httpclient/whitebox/SSLEchoTubeTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/SSLEchoTubeTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @compile/module=java.net.http ../../../../../../lib/jdk/test/lib/net/SimpleSSLContext.java * @modules java.net.http/jdk.internal.net.http - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * java.net.http/jdk.internal.net.http.SSLEchoTubeTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/SSLFlowDelegateTestDriver.java b/test/jdk/java/net/httpclient/whitebox/SSLFlowDelegateTestDriver.java index a49f53a844a..cb8e9801ca8 100644 --- a/test/jdk/java/net/httpclient/whitebox/SSLFlowDelegateTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/SSLFlowDelegateTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * downReader doesn't request any * @compile/module=java.net.http ../../../../../../lib/jdk/test/lib/net/SimpleSSLContext.java * @modules java.net.http/jdk.internal.net.http - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djavax.net.debug=ssl:handshake * java.net.http/jdk.internal.net.http.SSLFlowDelegateTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/SSLTubeTestDriver.java b/test/jdk/java/net/httpclient/whitebox/SSLTubeTestDriver.java index b1994777b14..2c73de26648 100644 --- a/test/jdk/java/net/httpclient/whitebox/SSLTubeTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/SSLTubeTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @compile/module=java.net.http ../../../../../../lib/jdk/test/lib/net/SimpleSSLContext.java * @modules java.net.http/jdk.internal.net.http - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * java.net.http/jdk.internal.net.http.SSLTubeTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/SelectorTestDriver.java b/test/jdk/java/net/httpclient/whitebox/SelectorTestDriver.java index 226e644e903..54d66d04cff 100644 --- a/test/jdk/java/net/httpclient/whitebox/SelectorTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/SelectorTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,5 +25,5 @@ * @test * @bug 8151299 8164704 * @modules java.net.http/jdk.internal.net.http - * @run testng java.net.http/jdk.internal.net.http.SelectorTest + * @run junit java.net.http/jdk.internal.net.http.SelectorTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/WindowControllerTestDriver.java b/test/jdk/java/net/httpclient/whitebox/WindowControllerTestDriver.java index 7943bfceaa0..16ac4aaefb8 100644 --- a/test/jdk/java/net/httpclient/whitebox/WindowControllerTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/WindowControllerTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,5 +26,5 @@ * @bug 8207960 * @modules java.net.http/jdk.internal.net.http * @summary Non-negative WINDOW_UPDATE increments may leave the stream window size negative - * @run testng/othervm java.net.http/jdk.internal.net.http.WindowControllerTest + * @run junit/othervm java.net.http/jdk.internal.net.http.WindowControllerTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/WrapperTestDriver.java b/test/jdk/java/net/httpclient/whitebox/WrapperTestDriver.java index 7ea2b07e3a7..dfc808ff68b 100644 --- a/test/jdk/java/net/httpclient/whitebox/WrapperTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/WrapperTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,5 +24,5 @@ /* * @test * @modules java.net.http/jdk.internal.net.http - * @run testng java.net.http/jdk.internal.net.http.WrapperTest + * @run junit java.net.http/jdk.internal.net.http.WrapperTest */ diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AbstractSSLTubeTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AbstractSSLTubeTest.java index 944f8ae0872..699b537c980 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AbstractSSLTubeTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AbstractSSLTubeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,17 +26,13 @@ package jdk.internal.net.http; import jdk.internal.net.http.common.FlowTube; import jdk.internal.net.http.common.SSLTube; import jdk.internal.net.http.common.Utils; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.nio.ByteBuffer; import java.util.List; -import java.util.StringTokenizer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java index 415caeb1196..2e9672e4725 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,6 @@ package jdk.internal.net.http; import jdk.internal.net.http.common.HttpHeadersBuilder; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.testng.annotations.AfterClass; import java.lang.ref.Reference; import java.net.Authenticator; @@ -55,12 +52,15 @@ import static java.util.stream.Collectors.joining; import static java.net.http.HttpClient.Version.HTTP_1_1; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpClient.Builder.NO_PROXY; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; public class AuthenticationFilterTest { - @DataProvider(name = "uris") - public Object[][] responses() { + public static Object[][] responses() { return new Object[][] { { "http://foo.com", HTTP_1_1, null }, { "http://foo.com", HTTP_2, null }, @@ -135,7 +135,8 @@ public class AuthenticationFilterTest { return s == null || s.isEmpty(); } - @Test(dataProvider = "uris") + @ParameterizedTest + @MethodSource("responses") public void testAuthentication(String uri, Version v, String proxy) throws Exception { String test = format("testAuthentication: {\"%s\", %s, \"%s\"}", uri, v, proxy); try { @@ -146,8 +147,8 @@ public class AuthenticationFilterTest { } } - @AfterClass - public void printDiagnostic() { + @AfterAll + public static void printDiagnostic() { if (FAILED.isEmpty()) { out.println("All tests passed"); return; @@ -183,7 +184,7 @@ public class AuthenticationFilterTest { HttpClientImpl client = facade.impl; AuthenticationFilter filter = new AuthenticationFilter(); - assertEquals(authenticator.COUNTER.get(), 0); + assertEquals(0, authenticator.COUNTER.get()); // Creates the first HttpRequestImpl, and call filter.request() with // it. The expectation is that the filter will not add any credentials, @@ -202,7 +203,7 @@ public class AuthenticationFilterTest { HttpHeaders hdrs = req.getSystemHeadersBuilder().build(); assertFalse(hdrs.firstValue(authorization(true)).isPresent()); assertFalse(hdrs.firstValue(authorization(false)).isPresent()); - assertEquals(authenticator.COUNTER.get(), 0); + assertEquals(0, authenticator.COUNTER.get()); // Creates the Response to the first request, and call filter.response // with it. That response has a 401 or 407 status code. @@ -221,9 +222,9 @@ public class AuthenticationFilterTest { out.println("Checking filter's response to " + unauthorized + " from " + uri); - assertTrue(next != null, "next should not be null"); + assertNotNull(next, "next should not be null"); String[] up = check(reqURI, next.getSystemHeadersBuilder().build(), proxy); - assertEquals(authenticator.COUNTER.get(), 1); + assertEquals(1, authenticator.COUNTER.get()); // Now simulate a new successful exchange to get the credentials in the cache // We first call filter.request with the request that was previously @@ -241,8 +242,8 @@ public class AuthenticationFilterTest { HttpHeaders h = HttpHeaders.of(Collections.emptyMap(), ACCEPT_ALL); response = new Response(next, exchange,h, null, 200, v); next = filter.response(response); - assertTrue(next == null, "next should be null"); - assertEquals(authenticator.COUNTER.get(), 1); + assertNull(next, "next should be null"); + assertEquals(1, authenticator.COUNTER.get()); // Now verify that the cache is used for the next request to the same server. // We're going to create a request to the same server by appending "/bar" to @@ -270,7 +271,7 @@ public class AuthenticationFilterTest { + " with proxy " + req2.proxy()); String[] up2 = check(reqURI, req2.getSystemHeadersBuilder().build(), proxy); assertTrue(Arrays.deepEquals(up, up2), format("%s:%s != %s:%s", up2[0], up2[1], up[0], up[1])); - assertEquals(authenticator.COUNTER.get(), 1); + assertEquals(1, authenticator.COUNTER.get()); // Now verify that the cache is not used if we send a request to a different server. // We're going to append ".bar" to the original request host name, and feed that @@ -316,7 +317,7 @@ public class AuthenticationFilterTest { java.util.stream.Stream.of(getAuthorization(h3, false)) .collect(joining(":"))); assertFalse(h3.firstValue(authorization(false)).isPresent()); - assertEquals(authenticator.COUNTER.get(), 1); + assertEquals(1, authenticator.COUNTER.get()); // Now we will verify that credentials for proxies are not used for servers and // conversely. @@ -365,7 +366,7 @@ public class AuthenticationFilterTest { String[] up4 = check(reqURI, h4, proxy); assertTrue(Arrays.deepEquals(up, up4), format("%s:%s != %s:%s", up4[0], up4[1], up[0], up[1])); } - assertEquals(authenticator.COUNTER.get(), 1); + assertEquals(1, authenticator.COUNTER.get()); if (proxy != null) { // Now if we were using a proxy, we're going to send the same request than @@ -380,7 +381,7 @@ public class AuthenticationFilterTest { MultiExchange multi5 = new MultiExchange(origReq5, req5, client, HttpResponse.BodyHandlers.replacing(null), null); out.println("Simulating new request to " + reqURI + " with a proxy " + req5.proxy()); - assertTrue(req5.proxy() == null, "req5.proxy() should be null"); + assertNull(req5.proxy(), "req5.proxy() should be null"); Exchange exchange5 = new Exchange<>(req5, multi5); filter.request(req5, multi5); out.println("Check that filter has not added server credentials from cache for " @@ -398,7 +399,7 @@ public class AuthenticationFilterTest { java.util.stream.Stream.of(getAuthorization(h5, true)) .collect(joining(":"))); assertFalse(h5.firstValue(authorization(true)).isPresent()); - assertEquals(authenticator.COUNTER.get(), 1); + assertEquals(1, authenticator.COUNTER.get()); // Now simulate a 401 response from the server HttpHeadersBuilder headers5Builder = new HttpHeadersBuilder(); @@ -410,11 +411,11 @@ public class AuthenticationFilterTest { out.println("Simulating " + unauthorized + " response from " + uri); HttpRequestImpl next5 = filter.response(response5); - assertEquals(authenticator.COUNTER.get(), 2); + assertEquals(2, authenticator.COUNTER.get()); out.println("Checking filter's response to " + unauthorized + " from " + uri); - assertTrue(next5 != null, "next5 should not be null"); + assertNotNull(next5, "next5 should not be null"); String[] up5 = check(reqURI, next5.getSystemHeadersBuilder().build(), null); // now simulate a 200 response from the server @@ -423,7 +424,7 @@ public class AuthenticationFilterTest { h = HttpHeaders.of(Map.of(), ACCEPT_ALL); response5 = new Response(next5, exchange5, h, null, 200, v); filter.response(response5); - assertEquals(authenticator.COUNTER.get(), 2); + assertEquals(2, authenticator.COUNTER.get()); // now send the request again, with proxy this time, and it should have both // server auth and proxy auth @@ -433,7 +434,7 @@ public class AuthenticationFilterTest { MultiExchange multi6 = new MultiExchange(origReq6, req6, client, HttpResponse.BodyHandlers.replacing(null), null); out.println("Simulating new request to " + reqURI + " with a proxy " + req6.proxy()); - assertTrue(req6.proxy() != null, "req6.proxy() should not be null"); + assertNotNull(req6.proxy(), "req6.proxy() should not be null"); Exchange exchange6 = new Exchange<>(req6, multi6); filter.request(req6, multi6); out.println("Check that filter has added server credentials from cache for " @@ -444,7 +445,7 @@ public class AuthenticationFilterTest { + reqURI + " (proxy: " + req6.proxy() + ")"); String[] up6 = check(reqURI, h6, proxy); assertTrue(Arrays.deepEquals(up, up6), format("%s:%s != %s:%s", up6[0], up6[1], up[0], up[1])); - assertEquals(authenticator.COUNTER.get(), 2); + assertEquals(2, authenticator.COUNTER.get()); } if (proxy == null && uri.contains("x/y/z")) { @@ -456,7 +457,7 @@ public class AuthenticationFilterTest { MultiExchange multi7 = new MultiExchange(origReq7, req7, client, HttpResponse.BodyHandlers.replacing(null), null); out.println("Simulating new request to " + reqURI7 + " with a proxy " + req7.proxy()); - assertTrue(req7.proxy() == null, "req7.proxy() should be null"); + assertNull(req7.proxy(), "req7.proxy() should be null"); Exchange exchange7 = new Exchange<>(req7, multi7); filter.request(req7, multi7); out.println("Check that filter has not added server credentials from cache for " @@ -475,7 +476,7 @@ public class AuthenticationFilterTest { java.util.stream.Stream.of(getAuthorization(h7, true)) .collect(joining(":"))); assertFalse(h7.firstValue(authorization(true)).isPresent()); - assertEquals(authenticator.COUNTER.get(), 1); + assertEquals(1, authenticator.COUNTER.get()); } @@ -516,7 +517,7 @@ public class AuthenticationFilterTest { out.println("user:password: " + u + ":" + p); String protocol = proxy != null ? "http" : reqURI.getScheme(); String expectedUser = "u." + protocol; - assertEquals(u, expectedUser); + assertEquals(expectedUser, u); String host = proxy == null ? reqURI.getHost() : proxy.substring(0, proxy.lastIndexOf(':')); int port = proxy == null ? reqURI.getPort() @@ -524,7 +525,7 @@ public class AuthenticationFilterTest { String expectedPw = concat(requestorType(proxy!=null), "basic", protocol, host, port, "earth", reqURI.toURL()); - assertEquals(p, expectedPw); + assertEquals(expectedPw, p); return new String[] {u, p}; } diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/DefaultProxy.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/DefaultProxy.java index 96d08ae2c34..819b02e7fc7 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/DefaultProxy.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/DefaultProxy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,9 @@ import java.net.ProxySelector; import java.net.URI; import java.net.http.HttpClient; import java.util.List; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; public class DefaultProxy { @@ -42,7 +43,7 @@ public class DefaultProxy { public void testDefault() { ProxySelector ps = getProxySelector(); System.out.println("HttpClientImpl proxySelector:" + ps); - assertEquals(ps, ProxySelector.getDefault()); + assertEquals(ProxySelector.getDefault(), ps); } // From the test driver @@ -56,21 +57,21 @@ public class DefaultProxy { URI uri = URI.create("http://foo.com/example.html"); List plist = ps.select(uri); System.out.println("proxy list for " + uri + " : " + plist); - assertEquals(plist.size(), 1); + assertEquals(1, plist.size()); Proxy proxy = plist.get(0); - assertEquals(proxy.type(), Proxy.Type.HTTP); + assertEquals(Proxy.Type.HTTP, proxy.type()); InetSocketAddress expectedAddr = InetSocketAddress.createUnresolved("foo.proxy.com", 9876); - assertEquals(proxy.address(), expectedAddr); + assertEquals(expectedAddr, proxy.address()); // nonProxyHosts uri = URI.create("http://foo.direct.com/example.html"); plist = ps.select(uri); System.out.println("proxy list for " + uri + " : " + plist); - assertEquals(plist.size(), 1); + assertEquals(1, plist.size()); proxy = plist.get(0); - assertEquals(proxy.type(), Proxy.Type.DIRECT); - assertEquals(proxy.address(), null); + assertEquals(Proxy.Type.DIRECT, proxy.type()); + assertEquals(null, proxy.address()); } // From the test driver @@ -83,21 +84,21 @@ public class DefaultProxy { URI uri = URI.create("https://foo.com/example.html"); List plist = ps.select(uri); System.out.println("proxy list for " + uri + " : " + plist); - assertEquals(plist.size(), 1); + assertEquals(1, plist.size()); Proxy proxy = plist.get(0); - assertEquals(proxy.type(), Proxy.Type.HTTP); + assertEquals(Proxy.Type.HTTP, proxy.type()); InetSocketAddress expectedAddr = InetSocketAddress.createUnresolved("secure.proxy.com", 5443); - assertEquals(proxy.address(), expectedAddr); + assertEquals(expectedAddr, proxy.address()); // nonProxyHosts uri = URI.create("https://foo.direct.com/example.html"); plist = ps.select(uri); System.out.println("proxy list for " + uri + " : " + plist); - assertEquals(plist.size(), 1); + assertEquals(1, plist.size()); proxy = plist.get(0); - assertEquals(proxy.type(), Proxy.Type.DIRECT); - assertEquals(proxy.address(), null); + assertEquals(Proxy.Type.DIRECT, proxy.type()); + assertEquals(null, proxy.address()); } } diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/FlowTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/FlowTest.java index 3e9e967c061..cd05196b653 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/FlowTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/FlowTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.nio.ByteBuffer; import java.util.List; -import java.util.Random; -import java.util.StringTokenizer; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; @@ -47,10 +45,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import javax.net.ssl.*; import jdk.internal.net.http.common.Utils; -import org.testng.annotations.Test; import jdk.internal.net.http.common.SSLFlowDelegate; -@Test +import org.junit.jupiter.api.Test; + public class FlowTest extends AbstractRandomTest { private final SubmissionPublisher> srcPublisher; @@ -241,7 +239,7 @@ public class FlowTest extends AbstractRandomTest { private void clientReader() { try { InputStream is = clientSock.getInputStream(); - final int bufsize = FlowTest.randomRange(512, 16 * 1024); + final int bufsize = AbstractRandomTest.randomRange(512, 16 * 1024); println("clientReader: bufsize = " + bufsize); while (true) { byte[] buf = new byte[bufsize]; @@ -315,8 +313,8 @@ public class FlowTest extends AbstractRandomTest { private final AtomicInteger loopCount = new AtomicInteger(); public String monitor() { - return "serverLoopback: loopcount = " + loopCount.toString() - + " clientRead: count = " + readCount.toString(); + return "serverLoopback: loopcount = " + loopCount.get() + + " clientRead: count = " + readCount.get(); } // thread2 @@ -324,7 +322,7 @@ public class FlowTest extends AbstractRandomTest { try { InputStream is = serverSock.getInputStream(); OutputStream os = serverSock.getOutputStream(); - final int bufsize = FlowTest.randomRange(512, 16 * 1024); + final int bufsize = AbstractRandomTest.randomRange(512, 16 * 1024); println("serverLoopback: bufsize = " + bufsize); byte[] bb = new byte[bufsize]; while (true) { diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/Http1HeaderParserTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/Http1HeaderParserTest.java index 9bde9109095..a4c7b76aba8 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/Http1HeaderParserTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/Http1HeaderParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,22 +36,22 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import sun.net.www.MessageHeader; -import org.testng.annotations.Test; -import org.testng.annotations.DataProvider; import static java.lang.System.out; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.util.stream.Collectors.toList; -import static org.testng.Assert.*; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; // Mostly verifies the "new" Http1HeaderParser returns the same results as the // tried and tested sun.net.www.MessageHeader. public class Http1HeaderParserTest { - @DataProvider(name = "responses") - public Object[][] responses() { + public static Object[][] responses() { List responses = new ArrayList<>(); String[] basic = @@ -316,7 +316,8 @@ public class Http1HeaderParserTest { } - @Test(dataProvider = "responses") + @ParameterizedTest + @MethodSource("responses") public void verifyHeaders(String respString) throws Exception { System.out.println("\ntesting:\n\t" + respString .replace("\r\n", "") @@ -339,7 +340,7 @@ public class Http1HeaderParserTest { String statusLine1 = messageHeaderMap.get(null).get(0); String statusLine2 = decoder.statusLine(); if (statusLine1.startsWith("HTTP")) {// skip the case where MH's messes up the status-line - assertEquals(statusLine2, statusLine1, "Status-line not equal"); + assertEquals(statusLine1, statusLine2, "Status-line not equal"); } else { assertTrue(statusLine2.startsWith("HTTP/1."), "Status-line not HTTP/1."); } @@ -356,7 +357,7 @@ public class Http1HeaderParserTest { assertHeadersEqual(messageHeaderMap, decoderMap1, "messageHeaderMap not equal to decoderMap1"); - assertEquals(availableBytes, b.remaining(), + assertEquals(b.remaining(), availableBytes, String.format("stream available (%d) not equal to remaining (%d)", availableBytes, b.remaining())); // byte at a time @@ -366,14 +367,13 @@ public class Http1HeaderParserTest { .collect(toList()); while (decoder.parse(buffers.remove(0)) != true); Map> decoderMap2 = decoder.headers().map(); - assertEquals(availableBytes, buffers.size(), + assertEquals(buffers.size(), availableBytes, "stream available not equals to remaining buffers"); - assertEquals(decoderMap1, decoderMap2, "decoder maps not equal"); + assertEquals(decoderMap2, decoderMap1, "decoder maps not equal"); } - @DataProvider(name = "errors") - public Object[][] errors() { + public static Object[][] errors() { List responses = new ArrayList<>(); // These responses are parsed, somewhat, by MessageHeaders but give @@ -451,12 +451,15 @@ public class Http1HeaderParserTest { return responses.stream().map(p -> new Object[] { p }).toArray(Object[][]::new); } - @Test(dataProvider = "errors", expectedExceptions = ProtocolException.class) + @ParameterizedTest + @MethodSource("errors") public void errors(String respString) throws ProtocolException { - byte[] bytes = respString.getBytes(US_ASCII); - Http1HeaderParser decoder = new Http1HeaderParser(); - ByteBuffer b = ByteBuffer.wrap(bytes); - decoder.parse(b); + assertThrows(ProtocolException.class, () -> { + byte[] bytes = respString.getBytes(US_ASCII); + Http1HeaderParser decoder = new Http1HeaderParser(); + ByteBuffer b = ByteBuffer.wrap(bytes); + decoder.parse(b); + }); } void assertHeadersEqual(Map> expected, @@ -466,7 +469,7 @@ public class Http1HeaderParserTest { if (expected.equals(actual)) return; - assertEquals(expected.size(), actual.size(), + assertEquals(actual.size(), expected.size(), format("%s. Expected size %d, actual size %s. %nexpected= %s,%n actual=%s.", msg, expected.size(), actual.size(), mapToString(expected), mapToString(actual))); @@ -479,7 +482,7 @@ public class Http1HeaderParserTest { if (key.equalsIgnoreCase(other.getKey())) { found = true; List otherValues = other.getValue(); - assertEquals(values.size(), otherValues.size(), + assertEquals(otherValues.size(), values.size(), format("%s. Expected list size %d, actual size %s", msg, values.size(), otherValues.size())); if (!(values.containsAll(otherValues) && otherValues.containsAll(values))) @@ -508,11 +511,11 @@ public class Http1HeaderParserTest { public static void main(String... args) throws Exception { Http1HeaderParserTest test = new Http1HeaderParserTest(); int count = 0; - for (Object[] objs : test.responses()) { + for (Object[] objs : Http1HeaderParserTest.responses()) { out.println("Testing " + count++ + ", " + objs[0]); test.verifyHeaders((String) objs[0]); } - for (Object[] objs : test.errors()) { + for (Object[] objs : Http1HeaderParserTest.errors()) { out.println("Testing " + count++ + ", " + objs[0]); try { test.errors((String) objs[0]); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java index f6bcdcb4d33..62ca237d2f1 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,10 +47,11 @@ import java.net.http.HttpResponse; import java.util.concurrent.atomic.AtomicReference; import jdk.internal.net.http.websocket.RawChannel; -import org.testng.annotations.Test; import static java.net.http.HttpResponse.BodyHandlers.discarding; import static java.util.concurrent.TimeUnit.SECONDS; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; /* * This test exercises mechanics of _independent_ reads and writes on the @@ -222,8 +223,8 @@ public class RawChannelTest { closeChannel(chan); }); exit.await(); // All done, we need to compare results: - assertEquals(clientRead.get(), serverWritten.get()); - assertEquals(serverRead.get(), clientWritten.get()); + assertEquals(serverWritten.get(), clientRead.get()); + assertEquals(clientWritten.get(), serverRead.get()); Throwable serverError = testServer.failed.get(); if (serverError != null) { throw new AssertionError("TestServer failed: " diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLEchoTubeTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLEchoTubeTest.java index 2884b74eee5..4316a46a25c 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLEchoTubeTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLEchoTubeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ import jdk.internal.net.http.common.FlowTube; import jdk.internal.net.http.common.SSLTube; import jdk.internal.net.http.common.SequentialScheduler; import jdk.internal.net.http.common.Utils; -import org.testng.annotations.Test; import java.io.IOException; import java.nio.ByteBuffer; @@ -44,7 +43,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -@Test +import org.junit.jupiter.api.Test; + public class SSLEchoTubeTest extends AbstractSSLTubeTest { @Test diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLFlowDelegateTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLFlowDelegateTest.java index 6b031bdfa58..32511de173b 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLFlowDelegateTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLFlowDelegateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,10 +58,11 @@ import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.SSLFlowDelegate; import jdk.internal.net.http.common.SubscriberWrapper; import jdk.internal.net.http.common.Utils; -import org.testng.Assert; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; // jtreg test definition for this test resides in SSLFlowDelegateTestDriver.java public class SSLFlowDelegateTest { @@ -70,38 +71,38 @@ public class SSLFlowDelegateTest { private static final Random random = new Random(); private static final byte DATA_BYTE = (byte) random.nextInt(); - private ExecutorService executor; - private SSLParameters sslParams; - private SSLServerSocket sslServerSocket; - private SSLEngine clientEngine; - private CompletableFuture testCompletion; + private static ExecutorService executor; + private static SSLParameters sslParams; + private static SSLServerSocket sslServerSocket; + private static SSLEngine clientEngine; + private static CompletableFuture testCompletion; - @BeforeTest - public void beforeTest() throws Exception { - this.executor = Executors.newCachedThreadPool(); - this.testCompletion = new CompletableFuture<>(); + @BeforeAll + public static void beforeTest() throws Exception { + executor = Executors.newCachedThreadPool(); + testCompletion = new CompletableFuture<>(); final SSLParameters sp = new SSLParameters(); sp.setApplicationProtocols(new String[]{ALPN}); - this.sslParams = sp; + sslParams = sp; var sslContext = SimpleSSLContextWhiteboxAdapter.findSSLContext(); - this.sslServerSocket = startServer(sslContext); - println(debugTag, "Server started at " + this.sslServerSocket.getInetAddress() + ":" - + this.sslServerSocket.getLocalPort()); + sslServerSocket = startServer(sslContext); + println(debugTag, "Server started at " + sslServerSocket.getInetAddress() + ":" + + sslServerSocket.getLocalPort()); - this.clientEngine = createClientEngine(sslContext); + clientEngine = createClientEngine(sslContext); } - @AfterTest - public void afterTest() throws Exception { - if (this.sslServerSocket != null) { - println(debugTag, "Closing server socket " + this.sslServerSocket); - this.sslServerSocket.close(); + @AfterAll + public static void afterTest() throws Exception { + if (sslServerSocket != null) { + println(debugTag, "Closing server socket " + sslServerSocket); + sslServerSocket.close(); } - if (this.executor != null) { - println(debugTag, "Shutting down the executor " + this.executor); - this.executor.shutdownNow(); + if (executor != null) { + println(debugTag, "Shutting down the executor " + executor); + executor.shutdownNow(); } } @@ -117,30 +118,30 @@ public class SSLFlowDelegateTest { } } - private SSLServerSocket createSSLServerSocket( + private static SSLServerSocket createSSLServerSocket( final SSLContext ctx, final InetSocketAddress bindAddr) throws IOException { final SSLServerSocketFactory fac = ctx.getServerSocketFactory(); final SSLServerSocket sslServerSocket = (SSLServerSocket) fac.createServerSocket(); sslServerSocket.setReuseAddress(false); - sslServerSocket.setSSLParameters(this.sslParams); + sslServerSocket.setSSLParameters(sslParams); sslServerSocket.bind(bindAddr); return sslServerSocket; } - private SSLServerSocket startServer(final SSLContext ctx) throws Exception { + private static SSLServerSocket startServer(final SSLContext ctx) throws Exception { final SSLServerSocket sslServerSocket = createSSLServerSocket(ctx, new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); final Runnable serverResponsePusher = new ServerResponsePusher(sslServerSocket, - this.testCompletion); + testCompletion); final Thread serverThread = new Thread(serverResponsePusher, "serverResponsePusher"); // start the thread which will accept() a socket connection and send data over it serverThread.start(); return sslServerSocket; } - private SSLEngine createClientEngine(final SSLContext ctx) { + private static SSLEngine createClientEngine(final SSLContext ctx) { final SSLEngine clientEngine = ctx.createSSLEngine(); - clientEngine.setSSLParameters(this.sslParams); + clientEngine.setSSLParameters(sslParams); clientEngine.setUseClientMode(true); return clientEngine; } @@ -170,7 +171,7 @@ public class SSLFlowDelegateTest { // in various places in this test. If the "testCompletion" completes before // the "soleExpectedAppData" completes (typically due to some exception), // then we complete the "soleExpectedAppData" too. - this.testCompletion.whenComplete((r, t) -> { + testCompletion.whenComplete((r, t) -> { if (soleExpectedAppData.isDone()) { return; } @@ -221,7 +222,7 @@ public class SSLFlowDelegateTest { println(debugTag, "Waiting for handshake to complete"); final String negotiatedALPN = sslFlowDelegate.alpn().join(); println(debugTag, "handshake completed, with negotiated ALPN: " + negotiatedALPN); - Assert.assertEquals(negotiatedALPN, ALPN, "unexpected ALPN negotiated"); + assertEquals(ALPN, negotiatedALPN, "unexpected ALPN negotiated"); try { // now wait for the initial (and the only) chunk of application data to be // received by the AppResponseReceiver @@ -254,7 +255,7 @@ public class SSLFlowDelegateTest { private void failTest(final CompletionException ce) { final Throwable cause = ce.getCause(); - Assert.fail(cause.getMessage() == null ? "test failed" : cause.getMessage(), cause); + fail(cause.getMessage() == null ? "test failed" : cause.getMessage(), cause); } // uses reflection to get hold of the SSLFlowDelegate.reader.outputQ member field, @@ -288,7 +289,7 @@ public class SSLFlowDelegateTest { } println(debugTag, "num unsolicited bytes so far = " + numUnsolicitated); } - Assert.assertEquals(numUnsolicitated, 0, + assertEquals(0, numUnsolicitated, "SSLFlowDelegate has accumulated " + numUnsolicitated + " unsolicited bytes"); } diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java index ac6a235b8e2..bb8d583e07b 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package jdk.internal.net.http; import jdk.internal.net.http.common.FlowTube; import jdk.internal.net.http.common.SSLFlowDelegate; import jdk.internal.net.http.common.Utils; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLParameters; @@ -51,7 +50,8 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SubmissionPublisher; import java.util.concurrent.atomic.AtomicInteger; -@Test +import org.junit.jupiter.api.Test; + public class SSLTubeTest extends AbstractSSLTubeTest { @Test @@ -125,7 +125,7 @@ public class SSLTubeTest extends AbstractSSLTubeTest { private void clientReader() { try { InputStream is = clientSock.getInputStream(); - final int bufsize = randomRange(512, 16 * 1024); + final int bufsize = AbstractRandomTest.randomRange(512, 16 * 1024); System.out.println("clientReader: bufsize = " + bufsize); while (true) { byte[] buf = new byte[bufsize]; @@ -137,7 +137,7 @@ public class SSLTubeTest extends AbstractSSLTubeTest { allBytesReceived.await(); System.out.println("clientReader: closing publisher"); publisher.close(); - sleep(2000); + AbstractSSLTubeTest.sleep(2000); Utils.close(is, clientSock); return; } @@ -206,13 +206,13 @@ public class SSLTubeTest extends AbstractSSLTubeTest { try { InputStream is = serverSock.getInputStream(); OutputStream os = serverSock.getOutputStream(); - final int bufsize = randomRange(512, 16 * 1024); + final int bufsize = AbstractRandomTest.randomRange(512, 16 * 1024); System.out.println("serverLoopback: bufsize = " + bufsize); byte[] bb = new byte[bufsize]; while (true) { int n = is.read(bb); if (n == -1) { - sleep(2000); + AbstractSSLTubeTest.sleep(2000); is.close(); os.close(); serverSock.close(); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SelectorTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SelectorTest.java index 5b8da3b9979..3027df0436e 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SelectorTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SelectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,20 +31,20 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import java.net.http.HttpClient; import java.net.http.HttpResponse; -import org.testng.annotations.Test; import jdk.internal.net.http.websocket.RawChannel; import static java.lang.System.out; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.util.concurrent.TimeUnit.SECONDS; import static java.net.http.HttpResponse.BodyHandlers.discarding; +import org.junit.jupiter.api.Test; + /** * Whitebox test of selector mechanics. Currently only a simple test * setting one read and one write event is done. It checks that the * write event occurs first, followed by the read event and then no * further events occur despite the conditions actually still existing. */ -@Test public class SelectorTest { AtomicInteger counter = new AtomicInteger(); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WindowControllerTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WindowControllerTest.java index 0a94f471575..5df3b4227e6 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WindowControllerTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WindowControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,92 +23,93 @@ package jdk.internal.net.http; -import org.testng.annotations.Test; import static jdk.internal.net.http.frame.SettingsFrame.DEFAULT_INITIAL_WINDOW_SIZE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertThrows; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; public class WindowControllerTest { @Test public void testConnectionWindowOverflow() { WindowController wc = new WindowController(); - assertEquals(wc.connectionWindowSize(), DEFAULT_INITIAL_WINDOW_SIZE); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.connectionWindowSize(), DEFAULT_INITIAL_WINDOW_SIZE); + assertEquals(DEFAULT_INITIAL_WINDOW_SIZE, wc.connectionWindowSize()); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(DEFAULT_INITIAL_WINDOW_SIZE, wc.connectionWindowSize()); wc.registerStream(1, DEFAULT_INITIAL_WINDOW_SIZE); wc.tryAcquire(DEFAULT_INITIAL_WINDOW_SIZE - 1, 1, null); - assertEquals(wc.connectionWindowSize(), 1); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.connectionWindowSize(), 1); + assertEquals(1, wc.connectionWindowSize()); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(1, wc.connectionWindowSize()); wc.increaseConnectionWindow(Integer.MAX_VALUE - 1 -1); - assertEquals(wc.connectionWindowSize(), Integer.MAX_VALUE - 1); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.connectionWindowSize(), Integer.MAX_VALUE - 1); + assertEquals(Integer.MAX_VALUE - 1, wc.connectionWindowSize()); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(Integer.MAX_VALUE - 1, wc.connectionWindowSize()); wc.increaseConnectionWindow(1); - assertEquals(wc.connectionWindowSize(), Integer.MAX_VALUE); - assertEquals(wc.increaseConnectionWindow(1), false); - assertEquals(wc.increaseConnectionWindow(100), false); - assertEquals(wc.increaseConnectionWindow(Integer.MAX_VALUE), false); - assertEquals(wc.connectionWindowSize(), Integer.MAX_VALUE); + assertEquals(Integer.MAX_VALUE, wc.connectionWindowSize()); + assertEquals(false, wc.increaseConnectionWindow(1)); + assertEquals(false, wc.increaseConnectionWindow(100)); + assertEquals(false, wc.increaseConnectionWindow(Integer.MAX_VALUE)); + assertEquals(Integer.MAX_VALUE, wc.connectionWindowSize()); } @Test public void testStreamWindowOverflow() { WindowController wc = new WindowController(); wc.registerStream(1, DEFAULT_INITIAL_WINDOW_SIZE); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 1), false); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 1), false); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 1), false); + assertEquals(false, wc.increaseStreamWindow(Integer.MAX_VALUE, 1)); + assertEquals(false, wc.increaseStreamWindow(Integer.MAX_VALUE, 1)); + assertEquals(false, wc.increaseStreamWindow(Integer.MAX_VALUE, 1)); wc.registerStream(3, DEFAULT_INITIAL_WINDOW_SIZE); - assertEquals(wc.increaseStreamWindow(100, 3), true); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 3), false); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 3), false); + assertEquals(true, wc.increaseStreamWindow(100, 3)); + assertEquals(false, wc.increaseStreamWindow(Integer.MAX_VALUE, 3)); + assertEquals(false, wc.increaseStreamWindow(Integer.MAX_VALUE, 3)); wc.registerStream(5, 0); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 5), true); - assertEquals(wc.increaseStreamWindow(1, 5), false); - assertEquals(wc.increaseStreamWindow(1, 5), false); - assertEquals(wc.increaseStreamWindow(10, 5), false); + assertEquals(true, wc.increaseStreamWindow(Integer.MAX_VALUE, 5)); + assertEquals(false, wc.increaseStreamWindow(1, 5)); + assertEquals(false, wc.increaseStreamWindow(1, 5)); + assertEquals(false, wc.increaseStreamWindow(10, 5)); wc.registerStream(7, -1); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 7), true); - assertEquals(wc.increaseStreamWindow(1, 7), true); - assertEquals(wc.increaseStreamWindow(1, 7), false); - assertEquals(wc.increaseStreamWindow(10, 7), false); + assertEquals(true, wc.increaseStreamWindow(Integer.MAX_VALUE, 7)); + assertEquals(true, wc.increaseStreamWindow(1, 7)); + assertEquals(false, wc.increaseStreamWindow(1, 7)); + assertEquals(false, wc.increaseStreamWindow(10, 7)); wc.registerStream(9, -1); - assertEquals(wc.increaseStreamWindow(1, 9), true); - assertEquals(wc.increaseStreamWindow(1, 9), true); - assertEquals(wc.increaseStreamWindow(1, 9), true); - assertEquals(wc.increaseStreamWindow(10, 9), true); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 9), false); + assertEquals(true, wc.increaseStreamWindow(1, 9)); + assertEquals(true, wc.increaseStreamWindow(1, 9)); + assertEquals(true, wc.increaseStreamWindow(1, 9)); + assertEquals(true, wc.increaseStreamWindow(10, 9)); + assertEquals(false, wc.increaseStreamWindow(Integer.MAX_VALUE, 9)); wc.registerStream(11, -10); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.increaseStreamWindow(1, 11), true); - assertEquals(wc.streamWindowSize(11), 1); - assertEquals(wc.increaseStreamWindow(Integer.MAX_VALUE, 11), false); - assertEquals(wc.streamWindowSize(11), 1); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(true, wc.increaseStreamWindow(1, 11)); + assertEquals(1, wc.streamWindowSize(11)); + assertEquals(false, wc.increaseStreamWindow(Integer.MAX_VALUE, 11)); + assertEquals(1, wc.streamWindowSize(11)); } @Test @@ -125,9 +126,9 @@ public class WindowControllerTest { wc.tryAcquire(51, 5 , null); wc.adjustActiveStreams(-200); - assertEquals(wc.streamWindowSize(1), -149); - assertEquals(wc.streamWindowSize(3), -150); - assertEquals(wc.streamWindowSize(5), -151); + assertEquals(-149, wc.streamWindowSize(1)); + assertEquals(-150, wc.streamWindowSize(3)); + assertEquals(-151, wc.streamWindowSize(5)); } static final Class IE = InternalError.class; diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WrapperTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WrapperTest.java index 6dad2cc75b5..bc69c425678 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WrapperTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/WrapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,10 @@ import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import org.testng.annotations.Test; import jdk.internal.net.http.common.SubscriberWrapper; -@Test +import org.junit.jupiter.api.Test; + public class WrapperTest { static final int LO_PRI = 1; static final int HI_PRI = 2; diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/DemandTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/DemandTest.java index 4ea604fd488..1ea72f472e9 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/DemandTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/DemandTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,15 +23,16 @@ package jdk.internal.net.http.common; -import org.testng.annotations.Test; - import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.atomic.AtomicReference; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; public class DemandTest { @@ -59,53 +60,61 @@ public class DemandTest { public void test03() { Demand d = new Demand(); d.increase(3); - assertEquals(d.decreaseAndGet(3), 3); + assertEquals(3, d.decreaseAndGet(3)); } @Test public void test04() { Demand d = new Demand(); d.increase(3); - assertEquals(d.decreaseAndGet(5), 3); + assertEquals(3, d.decreaseAndGet(5)); } @Test public void test05() { Demand d = new Demand(); d.increase(7); - assertEquals(d.decreaseAndGet(4), 4); + assertEquals(4, d.decreaseAndGet(4)); } @Test public void test06() { Demand d = new Demand(); - assertEquals(d.decreaseAndGet(3), 0); + assertEquals(0, d.decreaseAndGet(3)); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void test07() { - Demand d = new Demand(); - d.increase(0); + assertThrows(IllegalArgumentException.class, () -> { + Demand d = new Demand(); + d.increase(0); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void test08() { - Demand d = new Demand(); - d.increase(-1); + assertThrows(IllegalArgumentException.class, () -> { + Demand d = new Demand(); + d.increase(-1); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void test09() { - Demand d = new Demand(); - d.increase(10); - d.decreaseAndGet(0); + assertThrows(IllegalArgumentException.class, () -> { + Demand d = new Demand(); + d.increase(10); + d.decreaseAndGet(0); + }); } - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void test10() { - Demand d = new Demand(); - d.increase(13); - d.decreaseAndGet(-3); + assertThrows(IllegalArgumentException.class, () -> { + Demand d = new Demand(); + d.increase(13); + d.decreaseAndGet(-3); + }); } @Test @@ -169,7 +178,7 @@ public class DemandTest { assertTrue(d.isFulfilled()); } - @Test(invocationCount = 32) + @Test public void test15() throws InterruptedException { int N = Math.max(2, Runtime.getRuntime().availableProcessors() + 1); int M = ((N + 1) * N) / 2; // 1 + 2 + 3 + ... N @@ -187,7 +196,7 @@ public class DemandTest { error.compareAndSet(null, e); } try { - assertEquals(d.decreaseAndGet(j), j); + assertEquals(j, d.decreaseAndGet(j)); } catch (Throwable t) { error.compareAndSet(null, t); } finally { @@ -197,6 +206,6 @@ public class DemandTest { } stop.await(); assertTrue(d.isFulfilled()); - assertEquals(error.get(), null); + assertNull(error.get()); } } diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/MinimalFutureTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/MinimalFutureTest.java index 01798a645a2..2c33f6f0018 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/MinimalFutureTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/common/MinimalFutureTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,19 +23,19 @@ package jdk.internal.net.http.common; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import static org.testng.Assert.assertThrows; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertThrows; public class MinimalFutureTest { - @Test(dataProvider = "futures") + @ParameterizedTest + @MethodSource("futures") public void test(CompletableFuture mf) { ExecutorService executor = Executors.newSingleThreadExecutor(); try { @@ -134,8 +134,7 @@ public class MinimalFutureTest { } - @DataProvider(name = "futures") - public Object[][] futures() { + public static Object[][] futures() { MinimalFuture mf = new MinimalFuture<>(); mf.completeExceptionally(new Throwable()); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/frame/FramesDecoderTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/frame/FramesDecoderTest.java index 3db439d1c00..e8acc95c1d2 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/frame/FramesDecoderTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/frame/FramesDecoderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,15 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import org.testng.Assert; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; public class FramesDecoderTest { - abstract class TestFrameProcessor implements FramesDecoder.FrameProcessor { + abstract static class TestFrameProcessor implements FramesDecoder.FrameProcessor { protected volatile int count; public int numberOfFramesDecoded() { return count; } } @@ -69,17 +69,17 @@ public class FramesDecoderTest { assertTrue(frame instanceof DataFrame); DataFrame dataFrame = (DataFrame) frame; List list = dataFrame.getData(); - assertEquals(list.size(), 1); + assertEquals(1, list.size()); ByteBuffer data = list.get(0); byte[] bytes = new byte[data.remaining()]; data.get(bytes); if (count == 0) { - assertEquals(new String(bytes, UTF_8), "XXXX"); + assertEquals("XXXX", new String(bytes, UTF_8)); out.println("First data received:" + data); - assertEquals(data.position(), data.limit()); // since bytes read - assertEquals(data.limit(), data.capacity()); + assertEquals(data.limit(), data.position()); // since bytes read + assertEquals(data.capacity(), data.limit()); } else { - assertEquals(new String(bytes, UTF_8), "YYYY"); + assertEquals("YYYY", new String(bytes, UTF_8)); out.println("Second data received:" + data); } count++; @@ -89,7 +89,7 @@ public class FramesDecoderTest { out.println("Sending " + combined + " to decoder: "); decoder.decode(combined); - Assert.assertEquals(testFrameProcessor.numberOfFramesDecoded(), 2); + assertEquals(2, testFrameProcessor.numberOfFramesDecoded()); } @@ -119,15 +119,15 @@ public class FramesDecoderTest { assertTrue(frame instanceof DataFrame); DataFrame dataFrame = (DataFrame) frame; List list = dataFrame.getData(); - assertEquals(list.size(), 1); + assertEquals(1, list.size()); ByteBuffer data = list.get(0); byte[] bytes = new byte[data.remaining()]; data.get(bytes); - assertEquals(new String(bytes, UTF_8), "XXXX"); + assertEquals("XXXX", new String(bytes, UTF_8)); out.println("First data received:" + data); - assertEquals(data.position(), data.limit()); // since bytes read + assertEquals(data.limit(), data.position()); // since bytes read //assertNotEquals(data.limit(), data.capacity()); - assertEquals(data.capacity(), 1024 - 9 /*frame header*/); + assertEquals(1024 - 9 /*frame header*/, data.capacity()); count++; } }; @@ -135,6 +135,6 @@ public class FramesDecoderTest { out.println("Sending " + combined + " to decoder: "); decoder.decode(combined); - Assert.assertEquals(testFrameProcessor.numberOfFramesDecoded(), 1); + assertEquals(1, testFrameProcessor.numberOfFramesDecoded()); } } From a0c0a3617936bb024ee7a9325b98a49ccaab5041 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Thu, 5 Mar 2026 11:12:58 +0000 Subject: [PATCH 072/170] 8378600: Refactor tests under test/jdk/java/net/httpclient/http2 from TestNG to JUnit Reviewed-by: vyazici --- .../java/net/httpclient/http2/ErrorTest.java | 4 +- .../httpclient/http2/FixedThreadPoolTest.java | 6 +- .../httpclient/http2/H2SelectorVTTest.java | 10 +-- .../httpclient/http2/ImplicitPushCancel.java | 35 +++++---- .../java/net/httpclient/http2/NoBodyTest.java | 10 +-- .../net/httpclient/http2/PostPutTest.java | 36 ++++----- .../http2/PushPromiseContinuation.java | 49 ++++++------ .../net/httpclient/http2/RedirectTest.java | 7 +- .../java/net/httpclient/http2/ServerPush.java | 61 ++++++++------- .../http2/ServerPushWithDiffTypes.java | 15 ++-- .../java/net/httpclient/http2/SimpleGet.java | 21 ++--- .../http2/StreamFlowControlTest.java | 78 ++++++++++--------- .../httpclient/http2/TrailingHeadersTest.java | 49 ++++++------ .../net/http/hpack/HeaderTableTest.java | 6 +- 14 files changed, 196 insertions(+), 191 deletions(-) diff --git a/test/jdk/java/net/httpclient/http2/ErrorTest.java b/test/jdk/java/net/httpclient/http2/ErrorTest.java index 6b36529b38f..0f3bafa571d 100644 --- a/test/jdk/java/net/httpclient/http2/ErrorTest.java +++ b/test/jdk/java/net/httpclient/http2/ErrorTest.java @@ -45,7 +45,7 @@ * java.net.http/jdk.internal.net.http.qpack.writers * java.security.jgss * @modules java.base/jdk.internal.util - * @run testng/othervm/timeout=60 -Djavax.net.debug=ssl -Djdk.httpclient.HttpClient.log=all ErrorTest + * @run junit/othervm/timeout=60 -Djavax.net.debug=ssl -Djdk.httpclient.HttpClient.log=all ErrorTest * @summary check exception thrown when bad TLS parameters selected */ @@ -67,7 +67,7 @@ import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.test.lib.net.SimpleSSLContext; import static java.net.http.HttpClient.Version.HTTP_2; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; /** * When selecting an unacceptable cipher suite the TLS handshake will fail. diff --git a/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java b/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java index 2378b0b6982..d788d39b441 100644 --- a/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java +++ b/test/jdk/java/net/httpclient/http2/FixedThreadPoolTest.java @@ -30,7 +30,7 @@ * jdk.test.lib.Asserts * jdk.test.lib.Utils * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors FixedThreadPoolTest + * @run junit/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors FixedThreadPoolTest */ import java.net.*; @@ -51,7 +51,7 @@ import static jdk.test.lib.Asserts.assertFileContentsEqual; import static jdk.test.lib.Utils.createTempFile; import static jdk.test.lib.Utils.createTempFileOfSize; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; public class FixedThreadPoolTest implements HttpServerAdapters { @@ -92,7 +92,7 @@ public class FixedThreadPoolTest implements HttpServerAdapters { } @Test - public static void test() throws Exception { + public void test() throws Exception { try { initialize(); simpleTest(false); diff --git a/test/jdk/java/net/httpclient/http2/H2SelectorVTTest.java b/test/jdk/java/net/httpclient/http2/H2SelectorVTTest.java index 85d4012494a..7adfd57319c 100644 --- a/test/jdk/java/net/httpclient/http2/H2SelectorVTTest.java +++ b/test/jdk/java/net/httpclient/http2/H2SelectorVTTest.java @@ -38,7 +38,7 @@ import jdk.test.lib.net.SimpleSSLContext; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.Version.HTTP_2; @@ -166,21 +166,21 @@ class H2SelectorVTTest implements HttpServerAdapters { final HttpRequest req1 = reqBuilder.copy().GET().build(); System.out.println("\nIssuing request: " + req1); final HttpResponse resp1 = client.send(req1, BodyHandlers.ofString()); - Assertions.assertEquals(200, resp1.statusCode(), "unexpected response code for GET request"); + assertEquals(200, resp1.statusCode(), "unexpected response code for GET request"); assertSelectorThread(client); // POST final HttpRequest req2 = reqBuilder.copy().POST(BodyPublishers.ofString("foo")).build(); System.out.println("\nIssuing request: " + req2); final HttpResponse resp2 = client.send(req2, BodyHandlers.ofString()); - Assertions.assertEquals(200, resp2.statusCode(), "unexpected response code for POST request"); + assertEquals(200, resp2.statusCode(), "unexpected response code for POST request"); assertSelectorThread(client); // HEAD final HttpRequest req3 = reqBuilder.copy().HEAD().build(); System.out.println("\nIssuing request: " + req3); final HttpResponse resp3 = client.send(req3, BodyHandlers.ofString()); - Assertions.assertEquals(200, resp3.statusCode(), "unexpected response code for HEAD request"); + assertEquals(200, resp3.statusCode(), "unexpected response code for HEAD request"); assertSelectorThread(client); } } @@ -219,6 +219,6 @@ class H2SelectorVTTest implements HttpServerAdapters { msg = "%s not found in %s".formatted(name, threads); System.out.printf("%s: %s%n", status, msg); } - Assertions.assertEquals(!isTCPSelectorThreadVirtual(), found, msg); + assertEquals(!isTCPSelectorThreadVirtual(), found, msg); } } diff --git a/test/jdk/java/net/httpclient/http2/ImplicitPushCancel.java b/test/jdk/java/net/httpclient/http2/ImplicitPushCancel.java index c75a62d0f42..5bcaf95c6fc 100644 --- a/test/jdk/java/net/httpclient/http2/ImplicitPushCancel.java +++ b/test/jdk/java/net/httpclient/http2/ImplicitPushCancel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,responses,trace * ImplicitPushCancel @@ -51,15 +51,16 @@ import java.util.concurrent.ConcurrentMap; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.Http2TestExchange; import jdk.httpclient.test.lib.http2.Http2Handler; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; public class ImplicitPushCancel { - static Map PUSH_PROMISES = Map.of( + static final Map PUSH_PROMISES = Map.of( "/x/y/z/1", "the first push promise body", "/x/y/z/2", "the second push promise body", "/x/y/z/3", "the third push promise body", @@ -72,11 +73,11 @@ public class ImplicitPushCancel { ); static final String MAIN_RESPONSE_BODY = "the main response body"; - Http2TestServer server; - URI uri; + private static Http2TestServer server; + private static URI uri; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { server = new Http2TestServer(false, 0); Http2Handler handler = new ServerPushHandler(MAIN_RESPONSE_BODY, PUSH_PROMISES); @@ -87,13 +88,13 @@ public class ImplicitPushCancel { uri = new URI("http://localhost:" + port + "/foo/a/b/c"); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { server.stop(); } static final HttpResponse assert200ResponseCode(HttpResponse response) { - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); return response; } @@ -128,11 +129,11 @@ public class ImplicitPushCancel { promises.entrySet().stream().forEach(entry -> { HttpRequest request = entry.getKey(); HttpResponse response = entry.getValue().join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); if (PUSH_PROMISES.containsKey(request.uri().getPath())) { - assertEquals(response.body(), PUSH_PROMISES.get(request.uri().getPath())); + assertEquals(PUSH_PROMISES.get(request.uri().getPath()), response.body()); } else { - assertEquals(response.body(), MAIN_RESPONSE_BODY); + assertEquals(MAIN_RESPONSE_BODY, response.body()); } } ); diff --git a/test/jdk/java/net/httpclient/http2/NoBodyTest.java b/test/jdk/java/net/httpclient/http2/NoBodyTest.java index 3d30c54654a..2459c8eba4b 100644 --- a/test/jdk/java/net/httpclient/http2/NoBodyTest.java +++ b/test/jdk/java/net/httpclient/http2/NoBodyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 8087112 * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors + * @run junit/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors * -Djdk.internal.httpclient.debug=true * NoBodyTest */ @@ -47,10 +47,10 @@ import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.Http2TestExchange; import jdk.httpclient.test.lib.http2.Http2Handler; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_2; -@Test +import org.junit.jupiter.api.Test; + public class NoBodyTest { static int httpPort, httpsPort; static Http2TestServer httpServer, httpsServer; @@ -86,7 +86,7 @@ public class NoBodyTest { } @Test - public static void runtest() throws Exception { + public void runtest() throws Exception { try { initialize(); warmup(false); diff --git a/test/jdk/java/net/httpclient/http2/PostPutTest.java b/test/jdk/java/net/httpclient/http2/PostPutTest.java index 89b192f6171..84e86b556ca 100644 --- a/test/jdk/java/net/httpclient/http2/PostPutTest.java +++ b/test/jdk/java/net/httpclient/http2/PostPutTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * does not process any data. The client should read all data from the server and close the connection. * @library /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm/timeout=50 -Djdk.httpclient.HttpClient.log=all + * @run junit/othervm/timeout=50 -Djdk.httpclient.HttpClient.log=all * PostPutTest */ @@ -36,11 +36,6 @@ import jdk.httpclient.test.lib.http2.Http2Handler; import jdk.httpclient.test.lib.http2.Http2TestExchange; import jdk.httpclient.test.lib.http2.Http2TestServer; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - import java.io.IOException; import java.io.PrintStream; import java.net.URI; @@ -51,19 +46,24 @@ import java.net.http.HttpResponse; import static java.net.http.HttpClient.Version.HTTP_2; import static java.net.http.HttpRequest.BodyPublishers.ofByteArray; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PostPutTest { - Http2TestServer http2TestServer; - URI warmupURI, testHandlerBasicURI, testHandlerCloseBosURI, testHandleNegativeContentLengthURI; + private static Http2TestServer http2TestServer; + private static URI warmupURI, testHandlerBasicURI, testHandlerCloseBosURI, testHandleNegativeContentLengthURI; static PrintStream testLog = System.err; // As per jdk.internal.net.http.WindowController.DEFAULT_INITIAL_WINDOW_SIZE - final int DEFAULT_INITIAL_WINDOW_SIZE = (64 * 1024) - 1; + private static final int DEFAULT_INITIAL_WINDOW_SIZE = (64 * 1024) - 1; // Add on a small amount of arbitrary bytes to see if client hangs when receiving RST_STREAM - byte[] data = new byte[DEFAULT_INITIAL_WINDOW_SIZE + 10]; + private static byte[] data = new byte[DEFAULT_INITIAL_WINDOW_SIZE + 10]; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { http2TestServer = new Http2TestServer(false, 0); http2TestServer.addHandler(new WarmupHandler(), "/Warmup"); http2TestServer.addHandler(new TestHandlerBasic(), "/TestHandlerBasic"); @@ -81,15 +81,14 @@ public class PostPutTest { testLog.println("PostPutTest.setup(): testHandleNegativeContentLengthURI: " + testHandleNegativeContentLengthURI); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { testLog.println("PostPutTest.teardown(): Stopping server"); http2TestServer.stop(); data = null; } - @DataProvider(name = "variants") - public Object[][] variants() { + public static Object[][] variants() { HttpRequest over64kPost, over64kPut, over64kPostCloseBos, over64kPutCloseBos, over64kPostNegativeContentLength, over64kPutNegativeContentLength; over64kPost = HttpRequest.newBuilder().version(HTTP_2).POST(ofByteArray(data)).uri(testHandlerBasicURI).build(); over64kPut = HttpRequest.newBuilder().version(HTTP_2).PUT(ofByteArray(data)).uri(testHandlerBasicURI).build(); @@ -117,7 +116,8 @@ public class PostPutTest { .build(); } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") public void testOver64kPUT(HttpRequest req, String testMessage) { testLog.println("PostPutTest: Performing test: " + testMessage); HttpClient hc = HttpClient.newBuilder().version(HTTP_2).build(); diff --git a/test/jdk/java/net/httpclient/http2/PushPromiseContinuation.java b/test/jdk/java/net/httpclient/http2/PushPromiseContinuation.java index e9c6447e600..2d5b5dd4f4e 100644 --- a/test/jdk/java/net/httpclient/http2/PushPromiseContinuation.java +++ b/test/jdk/java/net/httpclient/http2/PushPromiseContinuation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,10 +31,9 @@ * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer * jdk.httpclient.test.lib.http2.BodyOutputStream * jdk.httpclient.test.lib.http2.OutgoingPushPromise - * @run testng/othervm PushPromiseContinuation + * @run junit/othervm PushPromiseContinuation */ - import javax.net.ssl.SSLSession; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -68,14 +67,13 @@ import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.frame.ContinuationFrame; import jdk.internal.net.http.frame.HeaderFrame; -import org.testng.TestException; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; - import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; public class PushPromiseContinuation { @@ -85,8 +83,8 @@ public class PushPromiseContinuation { static volatile int continuationCount; static final String mainPromiseBody = "Main Promise Body"; static final String mainResponseBody = "Main Response Body"; - Http2TestServer server; - URI uri; + private static Http2TestServer server; + private static URI uri; // Set up simple client-side push promise handler ConcurrentMap>> pushPromiseMap = new ConcurrentHashMap<>(); @@ -95,13 +93,13 @@ public class PushPromiseContinuation { pushPromiseMap.put(pushRequest, acceptor.apply(s)); }; - @BeforeMethod + @BeforeEach public void beforeMethod() { pushPromiseMap = new ConcurrentHashMap<>(); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { server = new Http2TestServer(false, 0); server.addHandler(new ServerPushHandler(), "/"); @@ -115,9 +113,8 @@ public class PushPromiseContinuation { uri = new URI("http://localhost:" + port + "/"); } - @AfterTest - public void teardown() { - pushPromiseMap = null; + @AfterAll + public static void teardown() { server.stop(); } @@ -195,29 +192,29 @@ public class PushPromiseContinuation { CompletableFuture> cf = client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph); - CompletionException t = expectThrows(CompletionException.class, () -> cf.join()); - assertEquals(t.getCause().getClass(), ProtocolException.class, + CompletionException t = assertThrows(CompletionException.class, () -> cf.join()); + assertEquals(ProtocolException.class, t.getCause().getClass(), "Expected a ProtocolException but got " + t.getCause()); System.err.println("Client received the following expected exception: " + t.getCause()); faultyServer.stop(); } private void verify(HttpResponse resp) { - assertEquals(resp.statusCode(), 200); - assertEquals(resp.body(), mainResponseBody); + assertEquals(200, resp.statusCode()); + assertEquals(mainResponseBody, resp.body()); if (pushPromiseMap.size() > 1) { System.err.println(pushPromiseMap.entrySet()); - throw new TestException("Results map size is greater than 1"); + fail("Results map size is greater than 1"); } else { // This will only iterate once for (HttpRequest r : pushPromiseMap.keySet()) { HttpResponse serverPushResp = pushPromiseMap.get(r).join(); // Received headers should be the same as the combined PushPromise // frame headers combined with the Continuation frame headers - assertEquals(testHeaders, r.headers()); + assertEquals(r.headers(), testHeaders); // Check status code and push promise body are as expected - assertEquals(serverPushResp.statusCode(), 200); - assertEquals(serverPushResp.body(), mainPromiseBody); + assertEquals(200, serverPushResp.statusCode()); + assertEquals(mainPromiseBody, serverPushResp.body()); } } } diff --git a/test/jdk/java/net/httpclient/http2/RedirectTest.java b/test/jdk/java/net/httpclient/http2/RedirectTest.java index e2acd807bd5..201b56513f6 100644 --- a/test/jdk/java/net/httpclient/http2/RedirectTest.java +++ b/test/jdk/java/net/httpclient/http2/RedirectTest.java @@ -30,7 +30,7 @@ * jdk.httpclient.test.lib.http2.Http2RedirectHandler * jdk.test.lib.Asserts * jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.HttpClient.log=frames,ssl,requests,responses,errors * -Djdk.internal.httpclient.debug=true * RedirectTest @@ -52,9 +52,10 @@ import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.Http2TestExchange; import jdk.httpclient.test.lib.http2.Http2RedirectHandler; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_2; +import org.junit.jupiter.api.Test; + public class RedirectTest implements HttpServerAdapters { static int httpPort; static HttpTestServer httpServer; @@ -135,7 +136,7 @@ public class RedirectTest implements HttpServerAdapters { } @Test - public static void test() throws Exception { + public void test() throws Exception { try { initialize(); simpleTest(); diff --git a/test/jdk/java/net/httpclient/http2/ServerPush.java b/test/jdk/java/net/httpclient/http2/ServerPush.java index 7f9c82fb28b..d38b867132b 100644 --- a/test/jdk/java/net/httpclient/http2/ServerPush.java +++ b/test/jdk/java/net/httpclient/http2/ServerPush.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * @build jdk.httpclient.test.lib.http2.Http2TestServer * jdk.httpclient.test.lib.http2.PushHandler * jdk.test.lib.Utils - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.HttpClient.log=errors,requests,responses * ServerPush */ @@ -48,13 +48,14 @@ import java.util.concurrent.*; import java.util.function.Consumer; import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.PushHandler; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; import static java.nio.charset.StandardCharsets.UTF_8; import static jdk.test.lib.Utils.createTempFileOfSize; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; public class ServerPush { @@ -66,11 +67,11 @@ public class ServerPush { static Path tempFile; - Http2TestServer server; - URI uri; + private static Http2TestServer server; + private static URI uri; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { tempFile = createTempFileOfSize(TEMP_FILE_PREFIX, null, FILE_SIZE); server = new Http2TestServer(false, 0); server.addHandler(new PushHandler(tempFile, LOOPS), "/"); @@ -82,8 +83,8 @@ public class ServerPush { uri = new URI("http://localhost:" + port + "/foo/a/b/c"); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { server.stop(); } @@ -109,10 +110,10 @@ public class ServerPush { System.err.println("results.size: " + resultMap.size()); for (HttpRequest r : resultMap.keySet()) { HttpResponse response = resultMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.body(), tempFileAsString); + assertEquals(200, response.statusCode()); + assertEquals(tempFileAsString, response.body()); } - assertEquals(resultMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultMap.size()); } // Test 2 - of(...) populating the given Map, everything as a String @@ -135,10 +136,10 @@ public class ServerPush { System.err.println("results.size: " + resultMap.size()); for (HttpRequest r : resultMap.keySet()) { HttpResponse response = resultMap.get(r).join(); - assertEquals(response.statusCode(), 200); - assertEquals(response.body(), tempFileAsString); + assertEquals(200, response.statusCode()); + assertEquals(tempFileAsString, response.body()); } - assertEquals(resultMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultMap.size()); } // --- Path --- @@ -177,11 +178,11 @@ public class ServerPush { for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8); - assertEquals(fileAsString, tempFileAsString); + assertEquals(tempFileAsString, fileAsString); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } // Test 4 - of(...) populating the given Map, everything as a Path @@ -204,11 +205,11 @@ public class ServerPush { for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); String fileAsString = new String(Files.readAllBytes(response.body()), UTF_8); - assertEquals(fileAsString, tempFileAsString); + assertEquals(tempFileAsString, fileAsString); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } // --- Consumer --- @@ -263,12 +264,12 @@ public class ServerPush { for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes(); String result = new String(ba, UTF_8); - assertEquals(result, tempFileAsString); + assertEquals(tempFileAsString, result); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } // Test 6 - of(...) populating the given Map, everything as a consumer of optional byte[] @@ -301,11 +302,11 @@ public class ServerPush { for (HttpRequest r : resultsMap.keySet()) { HttpResponse response = resultsMap.get(r).join(); - assertEquals(response.statusCode(), 200); + assertEquals(200, response.statusCode()); byte[] ba = byteArrayConsumerMap.get(r).getAccumulatedBytes(); String result = new String(ba, UTF_8); - assertEquals(result, tempFileAsString); + assertEquals(tempFileAsString, result); } - assertEquals(resultsMap.size(), LOOPS + 1); + assertEquals(LOOPS + 1, resultsMap.size()); } } diff --git a/test/jdk/java/net/httpclient/http2/ServerPushWithDiffTypes.java b/test/jdk/java/net/httpclient/http2/ServerPushWithDiffTypes.java index 3e12a20c15e..9cf2a3f7ae2 100644 --- a/test/jdk/java/net/httpclient/http2/ServerPushWithDiffTypes.java +++ b/test/jdk/java/net/httpclient/http2/ServerPushWithDiffTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,responses * ServerPushWithDiffTypes @@ -47,9 +47,10 @@ import jdk.httpclient.test.lib.http2.Http2TestServer; import jdk.httpclient.test.lib.http2.Http2TestExchange; import jdk.httpclient.test.lib.http2.Http2Handler; -import org.testng.annotations.Test; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; public class ServerPushWithDiffTypes { @@ -66,7 +67,7 @@ public class ServerPushWithDiffTypes { ); @Test - public static void test() throws Exception { + public void test() throws Exception { Http2TestServer server = null; try { server = new Http2TestServer(false, 0); @@ -93,7 +94,7 @@ public class ServerPushWithDiffTypes { results.put(request, cf); cf.join(); - assertEquals(results.size(), PUSH_PROMISES.size() + 1); + assertEquals(PUSH_PROMISES.size() + 1, results.size()); for (HttpRequest r : results.keySet()) { URI u = r.uri(); @@ -116,7 +117,7 @@ public class ServerPushWithDiffTypes { String expected = PUSH_PROMISES.get(r.uri().getPath()); if (expected == null) expected = "the main response body"; - assertEquals(result, expected); + assertEquals(expected, result); } } finally { server.stop(); diff --git a/test/jdk/java/net/httpclient/http2/SimpleGet.java b/test/jdk/java/net/httpclient/http2/SimpleGet.java index 692a6583b63..5df3174f820 100644 --- a/test/jdk/java/net/httpclient/http2/SimpleGet.java +++ b/test/jdk/java/net/httpclient/http2/SimpleGet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,11 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestUtil * jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm -XX:+CrashOnOutOfMemoryError SimpleGet - * @run testng/othervm -XX:+CrashOnOutOfMemoryError + * @run junit/othervm -XX:+CrashOnOutOfMemoryError SimpleGet + * @run junit/othervm -XX:+CrashOnOutOfMemoryError * -Dsimpleget.repeat=1 -Dsimpleget.chunks=1 -Dsimpleget.requests=1000 * SimpleGet - * @run testng/othervm -Dsimpleget.requests=150 + * @run junit/othervm -Dsimpleget.requests=150 * -Dsimpleget.chunks=16384 * -Djdk.httpclient.redirects.retrylimit=5 * -Djdk.httpclient.HttpClient.log=errors @@ -62,11 +62,12 @@ import javax.net.ssl.SSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.Assert; -import org.testng.annotations.Test; import static java.net.http.HttpClient.Version.HTTP_2; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class SimpleGet implements HttpServerAdapters { static HttpTestServer httpsServer; static HttpClient client = null; @@ -117,11 +118,11 @@ public class SimpleGet implements HttpServerAdapters { } public static void main(String[] args) throws Exception { - test(); + new SimpleGet().test(); } @Test - public static void test() throws Exception { + public void test() throws Exception { try { long prestart = System.nanoTime(); initialize(); @@ -132,7 +133,7 @@ public class SimpleGet implements HttpServerAdapters { .GET().build(); long start = System.nanoTime(); var resp = client.send(request, BodyHandlers.ofByteArrayConsumer(b -> {})); - Assert.assertEquals(resp.statusCode(), 200); + assertEquals(200, resp.statusCode()); long elapsed = System.nanoTime() - start; System.out.println("Stat: First request took: " + elapsed + " nanos (" + TimeUnit.NANOSECONDS.toMillis(elapsed) + " ms)"); final int max = property("simpleget.requests", 50); @@ -163,7 +164,7 @@ public class SimpleGet implements HttpServerAdapters { + connections.size() + " connections"); } } - list.forEach((cf) -> Assert.assertEquals(cf.join().statusCode(), 200)); + list.forEach((cf) -> assertEquals(200, cf.join().statusCode())); } catch (Throwable tt) { System.err.println("tt caught"); tt.printStackTrace(); diff --git a/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java b/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java index 3edf0b71305..a36fe29813c 100644 --- a/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java +++ b/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 8342075 8343855 * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.http2.Http2TestServer jdk.test.lib.net.SimpleSSLContext - * @run testng/othervm -Djdk.internal.httpclient.debug=true + * @run junit/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.connectionWindowSize=65535 * -Djdk.httpclient.windowsize=16384 * StreamFlowControlTest @@ -65,30 +65,30 @@ import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.frame.SettingsFrame; import jdk.test.lib.Utils; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class StreamFlowControlTest { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - String http2URI; - String https2URI; - final AtomicInteger reqid = new AtomicInteger(); + private static HttpTestServer http2TestServer; // HTTP/2 ( h2c ) + private static HttpTestServer https2TestServer; // HTTP/2 ( h2 ) + private static String http2URI; + private static String https2URI; + private static final AtomicInteger reqid = new AtomicInteger(); final static int WINDOW = Integer.getInteger("jdk.httpclient.windowsize", 2 * 16 * 1024); - @DataProvider(name = "variants") - public Object[][] variants() { + public static Object[][] variants() { return new Object[][] { { http2URI, false }, { https2URI, false }, @@ -111,7 +111,8 @@ public class StreamFlowControlTest { } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") void test(String uri, boolean sameClient) throws Exception @@ -142,7 +143,7 @@ public class StreamFlowControlTest { if (sameClient) { String key = response.headers().firstValue("X-Connection-Key").get(); if (label == null) label = key; - assertEquals(key, label, "Unexpected key for " + query); + assertEquals(label, key, "Unexpected key for " + query); } sent.join(); // we have to pull to get the exception, but slow enough @@ -175,7 +176,8 @@ public class StreamFlowControlTest { } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") void testAsync(String uri, boolean sameClient) { @@ -207,7 +209,7 @@ public class StreamFlowControlTest { if (sameClient) { String key = response.headers().firstValue("X-Connection-Key").get(); if (label == null) label = key; - assertEquals(key, label, "Unexpected key for " + query); + assertEquals(label, key, "Unexpected key for " + query); } sent.join(); long wait = uri.startsWith("https://") ? 800 : 350; @@ -264,38 +266,38 @@ public class StreamFlowControlTest { } } - @BeforeTest - public void setup() throws Exception { - var http2TestServer = new Http2TestServer("localhost", false, 0); - http2TestServer.addHandler(new Http2TestHandler(), "/http2/"); - this.http2TestServer = HttpTestServer.of(http2TestServer); - http2URI = "http://" + this.http2TestServer.serverAuthority() + "/http2/x"; + @BeforeAll + public static void setup() throws Exception { + var http2TestServerImpl = new Http2TestServer("localhost", false, 0); + http2TestServerImpl.addHandler(new Http2TestHandler(), "/http2/"); + http2TestServer = HttpTestServer.of(http2TestServerImpl); + http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/x"; - var https2TestServer = new Http2TestServer("localhost", true, sslContext); - https2TestServer.addHandler(new Http2TestHandler(), "/https2/"); - this.https2TestServer = HttpTestServer.of(https2TestServer); - this.https2TestServer.addHandler(new HttpHeadOrGetHandler(), "/https2/head/"); - https2URI = "https://" + this.https2TestServer.serverAuthority() + "/https2/x"; - String h2Head = "https://" + this.https2TestServer.serverAuthority() + "/https2/head/z"; + var https2TestServerImpl = new Http2TestServer("localhost", true, sslContext); + https2TestServerImpl.addHandler(new Http2TestHandler(), "/https2/"); + https2TestServer = HttpTestServer.of(https2TestServerImpl); + https2TestServer.addHandler(new HttpHeadOrGetHandler(), "/https2/head/"); + https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/x"; + String h2Head = "https://" + https2TestServer.serverAuthority() + "/https2/head/z"; // Override the default exchange supplier with a custom one to enable // particular test scenarios - http2TestServer.setExchangeSupplier(FCHttp2TestExchange::new); - https2TestServer.setExchangeSupplier(FCHttp2TestExchange::new); + http2TestServerImpl.setExchangeSupplier(FCHttp2TestExchange::new); + https2TestServerImpl.setExchangeSupplier(FCHttp2TestExchange::new); - this.http2TestServer.start(); - this.https2TestServer.start(); + http2TestServer.start(); + https2TestServer.start(); // warmup to eliminate delay due to SSL class loading and initialization. try (var client = HttpClient.newBuilder().sslContext(sslContext).build()) { var request = HttpRequest.newBuilder(URI.create(h2Head)).HEAD().build(); var resp = client.send(request, BodyHandlers.discarding()); - assertEquals(resp.statusCode(), 200); + assertEquals(200, resp.statusCode()); } } - @AfterTest - public void teardown() throws Exception { + @AfterAll + public static void teardown() throws Exception { http2TestServer.stop(); https2TestServer.stop(); } diff --git a/test/jdk/java/net/httpclient/http2/TrailingHeadersTest.java b/test/jdk/java/net/httpclient/http2/TrailingHeadersTest.java index 9fa6f8b728e..9ea331d2d84 100644 --- a/test/jdk/java/net/httpclient/http2/TrailingHeadersTest.java +++ b/test/jdk/java/net/httpclient/http2/TrailingHeadersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * @bug 8296410 * @library /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.http2.Http2TestServer - * @run testng/othervm -Djdk.httpclient.HttpClient.log=all TrailingHeadersTest + * @run junit/othervm -Djdk.httpclient.HttpClient.log=all TrailingHeadersTest */ import jdk.httpclient.test.lib.http2.OutgoingPushPromise; @@ -36,11 +36,6 @@ import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.frame.DataFrame; import jdk.internal.net.http.frame.HeaderFrame; import jdk.internal.net.http.frame.HeadersFrame; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLSession; import java.io.ByteArrayInputStream; @@ -74,24 +69,30 @@ import jdk.httpclient.test.lib.http2.BodyOutputStream; import static java.net.http.HttpClient.Version.HTTP_2; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; public class TrailingHeadersTest { - Http2TestServer http2TestServer; - URI trailingURI, trailng1xxURI, trailingPushPromiseURI, warmupURI; + private static Http2TestServer http2TestServer; + private static URI trailingURI, trailng1xxURI, trailingPushPromiseURI, warmupURI; static PrintStream testLog = System.err; // Set up simple client-side push promise handler - ConcurrentMap>> pushPromiseMap = new ConcurrentHashMap<>(); + private static ConcurrentMap>> pushPromiseMap = new ConcurrentHashMap<>(); - @BeforeMethod + @BeforeEach public void beforeMethod() { pushPromiseMap = new ConcurrentHashMap<>(); } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { Properties props = new Properties(); // For triggering trailing headers to send after Push Promise Response headers are sent props.setProperty("sendTrailingHeadersAfterPushPromise", "1"); @@ -119,12 +120,13 @@ public class TrailingHeadersTest { warmupURI = URI.create("http://" + http2TestServer.serverAuthority() + "/WarmupHandler"); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { http2TestServer.stop(); } - @Test(dataProvider = "httpRequests") + @ParameterizedTest + @MethodSource("uris") public void testTrailingHeaders(String description, HttpRequest hRequest, HttpResponse.PushPromiseHandler pph) { testLog.println("testTrailingHeaders(): " + description); HttpClient httpClient = HttpClient.newBuilder().build(); @@ -134,7 +136,7 @@ public class TrailingHeadersTest { testLog.println("testTrailingHeaders(): Performing request: " + hRequest); HttpResponse resp = cf.join(); - assertEquals(resp.statusCode(), 200, "Status code of response should be 200"); + assertEquals(200, resp.statusCode(), "Status code of response should be 200"); // Verify Push Promise was successful if necessary if (pph != null) @@ -144,14 +146,14 @@ public class TrailingHeadersTest { } private void verifyPushPromise() { - assertEquals(pushPromiseMap.size(), 1, "Push Promise should not be greater than 1"); + assertEquals(1, pushPromiseMap.size(), "Push Promise should not be greater than 1"); // This will only iterate once for (HttpRequest r : pushPromiseMap.keySet()) { CompletableFuture> serverPushResp = pushPromiseMap.get(r); // Get the push promise HttpResponse result if present HttpResponse resp = serverPushResp.join(); - assertEquals(resp.body(), "Sample_Push_Data", "Unexpected Push Promise response body"); - assertEquals(resp.statusCode(), 200, "Status code of Push Promise response should be 200"); + assertEquals("Sample_Push_Data", resp.body(), "Unexpected Push Promise response body"); + assertEquals(200, resp.statusCode(), "Status code of Push Promise response should be 200"); } } @@ -162,11 +164,10 @@ public class TrailingHeadersTest { httpClient.sendAsync(warmupReq, BodyHandlers.discarding()).join(); } - @DataProvider(name = "httpRequests") - public Object[][] uris() { + public static Object[][] uris() { HttpResponse.PushPromiseHandler pph = (initial, pushRequest, acceptor) -> { HttpResponse.BodyHandler s = HttpResponse.BodyHandlers.ofString(UTF_8); - pushPromiseMap.put(pushRequest, acceptor.apply(s)); + TrailingHeadersTest.pushPromiseMap.put(pushRequest, acceptor.apply(s)); }; HttpRequest httpGetTrailing = HttpRequest.newBuilder(trailingURI).version(HTTP_2) diff --git a/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HeaderTableTest.java b/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HeaderTableTest.java index 0eb1714da35..07e27a7f2fa 100644 --- a/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HeaderTableTest.java +++ b/test/jdk/java/net/httpclient/http2/java.net.http/jdk/internal/net/http/hpack/HeaderTableTest.java @@ -29,9 +29,9 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.junit.jupiter.api.Assertions; -import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; public class HeaderTableTest extends SimpleHeaderTableTest { @@ -76,7 +76,7 @@ public class HeaderTableTest extends SimpleHeaderTableTest { Set expectedIndexes = indexes.get(hName); int actualMinimalIndex = table.indexOf(hName, "blah-blah"); - Assertions.assertTrue(expectedIndexes.contains(-actualMinimalIndex)); + assertTrue(expectedIndexes.contains(-actualMinimalIndex)); }); } From dfea6eb9f84142aaa3e51181ea345e8575729ea2 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Thu, 5 Mar 2026 11:13:15 +0000 Subject: [PATCH 073/170] 8378598: Refactor tests under test/jdk/java/net/httpclient/websocket from TestNG to JUnit Reviewed-by: vyazici --- .../java/net/httpclient/websocket/Abort.java | 31 ++++---- .../httpclient/websocket/AutomaticPong.java | 32 +++++---- .../websocket/BlowupOutputQueue.java | 9 ++- .../websocket/HandshakeUrlEncodingTest.java | 50 ++++++------- .../websocket/HeaderWriterDriver.java | 4 +- .../httpclient/websocket/MaskerDriver.java | 4 +- .../websocket/MessageQueueDriver.java | 4 +- .../websocket/PendingBinaryPingClose.java | 12 ++-- .../websocket/PendingBinaryPongClose.java | 12 ++-- .../websocket/PendingOperations.java | 12 ++-- .../websocket/PendingPingBinaryClose.java | 12 ++-- .../websocket/PendingPingTextClose.java | 12 ++-- .../websocket/PendingPongBinaryClose.java | 12 ++-- .../websocket/PendingPongTextClose.java | 12 ++-- .../websocket/PendingTextPingClose.java | 12 ++-- .../websocket/PendingTextPongClose.java | 12 ++-- .../httpclient/websocket/ReaderDriver.java | 6 +- .../httpclient/websocket/SecureSupport.java | 11 +-- .../net/httpclient/websocket/SendTest.java | 16 ++--- .../net/httpclient/websocket/Support.java | 6 +- .../websocket/WSHandshakeExceptionTest.java | 55 +++++++-------- .../websocket/WebSocketBuilderTest.java | 32 ++++----- .../websocket/WebSocketExtendedTest.java | 70 ++++++++++--------- .../websocket/WebSocketProxyTest.java | 28 ++++---- .../httpclient/websocket/WebSocketTest.java | 42 ++++++----- .../net/http/websocket/HeaderWriterTest.java | 9 +-- .../net/http/websocket/MaskerTest.java | 20 +++--- .../net/http/websocket/MessageQueueTest.java | 44 ++++++------ .../net/http/websocket/ReaderTest.java | 25 +++---- .../websocket/security/WSSanityTest.java | 37 +++++----- 30 files changed, 333 insertions(+), 310 deletions(-) diff --git a/test/jdk/java/net/httpclient/websocket/Abort.java b/test/jdk/java/net/httpclient/websocket/Abort.java index 99c94de83f0..a6088f8cce2 100644 --- a/test/jdk/java/net/httpclient/websocket/Abort.java +++ b/test/jdk/java/net/httpclient/websocket/Abort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,11 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.websocket.debug=true * Abort */ -import org.testng.annotations.Test; import java.io.IOException; import java.net.ProtocolException; @@ -44,10 +43,12 @@ import java.util.concurrent.TimeoutException; import static java.net.http.HttpClient.newHttpClient; import static java.net.http.WebSocket.NORMAL_CLOSURE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.Test; public class Abort { @@ -79,7 +80,7 @@ public class Abort { TimeUnit.SECONDS.sleep(5); List inv = listener.invocationsSoFar(); // no more invocations after onOpen as WebSocket was aborted - assertEquals(inv, List.of(MockListener.Invocation.onOpen(webSocket))); + assertEquals(List.of(MockListener.Invocation.onOpen(webSocket)), inv); } finally { webSocket.abort(); } @@ -119,7 +120,7 @@ public class Abort { List expected = List.of( MockListener.Invocation.onOpen(webSocket), MockListener.Invocation.onText(webSocket, "", true)); - assertEquals(inv, expected); + assertEquals(expected, inv); } finally { webSocket.abort(); } @@ -159,7 +160,7 @@ public class Abort { List expected = List.of( MockListener.Invocation.onOpen(webSocket), MockListener.Invocation.onBinary(webSocket, ByteBuffer.allocate(0), true)); - assertEquals(inv, expected); + assertEquals(expected, inv); } finally { webSocket.abort(); } @@ -198,7 +199,7 @@ public class Abort { List expected = List.of( MockListener.Invocation.onOpen(webSocket), MockListener.Invocation.onPing(webSocket, ByteBuffer.allocate(0))); - assertEquals(inv, expected); + assertEquals(expected, inv); } finally { webSocket.abort(); } @@ -237,7 +238,7 @@ public class Abort { List expected = List.of( MockListener.Invocation.onOpen(webSocket), MockListener.Invocation.onPong(webSocket, ByteBuffer.allocate(0))); - assertEquals(inv, expected); + assertEquals(expected, inv); } finally { webSocket.abort(); } @@ -277,7 +278,7 @@ public class Abort { List expected = List.of( MockListener.Invocation.onOpen(webSocket), MockListener.Invocation.onClose(webSocket, 1005, "")); - assertEquals(inv, expected); + assertEquals(expected, inv); } finally { webSocket.abort(); } @@ -318,7 +319,7 @@ public class Abort { MockListener.Invocation.onOpen(webSocket), MockListener.Invocation.onError(webSocket, ProtocolException.class)); System.out.println("actual invocations:" + Arrays.toString(inv.toArray())); - assertEquals(inv, expected); + assertEquals(expected, inv); } finally { webSocket.abort(); } @@ -396,7 +397,7 @@ public class Abort { ws.abort(); assertTrue(ws.isInputClosed()); assertTrue(ws.isOutputClosed()); - assertEquals(ws.getSubprotocol(), ""); + assertEquals("", ws.getSubprotocol()); } // at this point valid requests MUST be a no-op: for (int j = 0; j < 3; j++) { diff --git a/test/jdk/java/net/httpclient/websocket/AutomaticPong.java b/test/jdk/java/net/httpclient/websocket/AutomaticPong.java index 1999781b82f..b438cb8e728 100644 --- a/test/jdk/java/net/httpclient/websocket/AutomaticPong.java +++ b/test/jdk/java/net/httpclient/websocket/AutomaticPong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,13 +24,11 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.websocket.debug=true * AutomaticPong */ import jdk.internal.net.http.websocket.Frame; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.IOException; import java.net.http.WebSocket; @@ -39,10 +37,14 @@ import java.nio.charset.StandardCharsets; import java.util.List; import static java.net.http.HttpClient.newHttpClient; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class AutomaticPong { /* @@ -86,7 +88,7 @@ public class AutomaticPong { MockListener.Invocation.onPing(webSocket, hello), MockListener.Invocation.onClose(webSocket, 1005, "") ); - assertEquals(actual, expected); + assertEquals(expected, actual); } finally { webSocket.abort(); } @@ -104,7 +106,8 @@ public class AutomaticPong { * b) the last Pong corresponds to the last Ping * c) there are no unrelated Pongs */ - @Test(dataProvider = "nPings") + @ParameterizedTest + @MethodSource("nPings") public void automaticPongs(int nPings) throws Exception { // big enough to not bother with resize ByteBuffer buffer = ByteBuffer.allocate(65536); @@ -133,7 +136,7 @@ public class AutomaticPong { .join(); try { List inv = listener.invocations(); - assertEquals(inv.size(), nPings + 2); // n * onPing + onOpen + onClose + assertEquals(nPings + 2, inv.size()); // n * onPing + onOpen + onClose ByteBuffer data = server.read(); Frame.Reader reader = new Frame.Reader(); @@ -171,7 +174,7 @@ public class AutomaticPong { closed = true; return; } - assertEquals(value, Frame.Opcode.PONG); + assertEquals(Frame.Opcode.PONG, value); } @Override @@ -182,7 +185,7 @@ public class AutomaticPong { @Override public void payloadLen(long value) { if (!closed) - assertEquals(value, 4); + assertEquals(4, value); } @Override @@ -222,8 +225,7 @@ public class AutomaticPong { } - @DataProvider(name = "nPings") - public Object[][] nPings() { + public static Object[][] nPings() { return new Object[][]{{1}, {2}, {4}, {8}, {9}, {256}}; } } diff --git a/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java b/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java index 7bf2564a04f..1865ca05e4f 100644 --- a/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java +++ b/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,14 +24,12 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.websocket.debug=true * BlowupOutputQueue */ -import org.testng.annotations.Test; - import java.io.IOException; import java.net.http.WebSocket; import java.nio.ByteBuffer; @@ -43,7 +41,8 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static org.testng.Assert.assertFalse; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertFalse; public class BlowupOutputQueue extends PendingOperations { diff --git a/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java index 25a6893ff13..6854cacbcc2 100644 --- a/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java +++ b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestServerConfigurator * @modules java.net.http/jdk.internal.net.http.common * jdk.httpserver - * @run testng/othervm -Djdk.internal.httpclient.debug=true HandshakeUrlEncodingTest + * @run junit/othervm -Djdk.internal.httpclient.debug=true HandshakeUrlEncodingTest */ import com.sun.net.httpserver.HttpHandler; @@ -39,10 +39,6 @@ import com.sun.net.httpserver.HttpExchange; import jdk.httpclient.test.lib.common.TestServerConfigurator; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -58,20 +54,25 @@ import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; - import static java.net.http.HttpClient.Builder.NO_PROXY; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; import static java.lang.System.out; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; + + public class HandshakeUrlEncodingTest { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpServer httpTestServer; - HttpsServer httpsTestServer; - String httpURI; - String httpsURI; + private static HttpServer httpTestServer; + private static HttpsServer httpsTestServer; + private static String httpURI; + private static String httpsURI; static String queryPart; @@ -79,8 +80,7 @@ public class HandshakeUrlEncodingTest { // a shared executor helps reduce the amount of threads created by the test static final ExecutorService executor = Executors.newCachedThreadPool(); - @DataProvider(name = "variants") - public Object[][] variants() { + public static Object[][] variants() { return new Object[][]{ { httpURI, false }, { httpsURI, false }, @@ -97,7 +97,8 @@ public class HandshakeUrlEncodingTest { .build(); } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") public void test(String uri, boolean sameClient) { HttpClient client = null; out.println("The url is " + uri); @@ -119,22 +120,21 @@ public class HandshakeUrlEncodingTest { final WebSocketHandshakeException wse = (WebSocketHandshakeException) t; assertNotNull(wse.getResponse()); assertNotNull(wse.getResponse().uri()); - assertNotNull(wse.getResponse().statusCode()); final String rawQuery = wse.getResponse().uri().getRawQuery(); final String expectedRawQuery = "&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; - assertEquals(rawQuery, expectedRawQuery); + assertEquals(expectedRawQuery, rawQuery); final String body = (String) wse.getResponse().body(); final String expectedBody = "/?" + expectedRawQuery; - assertEquals(body, expectedBody); + assertEquals(expectedBody, body); out.println("Status code is " + wse.getResponse().statusCode()); out.println("Response is " + wse.getResponse()); - assertEquals(wse.getResponse().statusCode(), 400); + assertEquals(400, wse.getResponse().statusCode()); } } } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); queryPart = "?&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; httpTestServer = HttpServer.create(sa, 10); @@ -164,8 +164,8 @@ public class HandshakeUrlEncodingTest { httpsTestServer.start(); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { httpTestServer.stop(0); httpsTestServer.stop(0); executor.shutdownNow(); diff --git a/test/jdk/java/net/httpclient/websocket/HeaderWriterDriver.java b/test/jdk/java/net/httpclient/websocket/HeaderWriterDriver.java index 6293b1b6c71..75ae5423f00 100644 --- a/test/jdk/java/net/httpclient/websocket/HeaderWriterDriver.java +++ b/test/jdk/java/net/httpclient/websocket/HeaderWriterDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8159053 * @modules java.net.http/jdk.internal.net.http.websocket:open - * @run testng/othervm + * @run junit/othervm * --add-reads java.net.http=ALL-UNNAMED * java.net.http/jdk.internal.net.http.websocket.HeaderWriterTest */ diff --git a/test/jdk/java/net/httpclient/websocket/MaskerDriver.java b/test/jdk/java/net/httpclient/websocket/MaskerDriver.java index b84ea1fff5c..e81417c25ef 100644 --- a/test/jdk/java/net/httpclient/websocket/MaskerDriver.java +++ b/test/jdk/java/net/httpclient/websocket/MaskerDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8159053 * @modules java.net.http/jdk.internal.net.http.websocket:open - * @run testng/othervm + * @run junit/othervm * --add-reads java.net.http=ALL-UNNAMED * java.net.http/jdk.internal.net.http.websocket.MaskerTest */ diff --git a/test/jdk/java/net/httpclient/websocket/MessageQueueDriver.java b/test/jdk/java/net/httpclient/websocket/MessageQueueDriver.java index 9831bb59297..68a23d0be88 100644 --- a/test/jdk/java/net/httpclient/websocket/MessageQueueDriver.java +++ b/test/jdk/java/net/httpclient/websocket/MessageQueueDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8159053 * @modules java.net.http/jdk.internal.net.http.websocket:open - * @run testng/othervm + * @run junit/othervm * --add-reads java.net.http=ALL-UNNAMED * java.net.http/jdk.internal.net.http.websocket.MessageQueueTest */ diff --git a/test/jdk/java/net/httpclient/websocket/PendingBinaryPingClose.java b/test/jdk/java/net/httpclient/websocket/PendingBinaryPingClose.java index 5a410251593..4a5ae315e91 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingBinaryPingClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingBinaryPingClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,28 +24,30 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.sendBufferSize=8192 * -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.websocket.debug=true * PendingBinaryPingClose */ -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingBinaryPingClose extends PendingOperations { CompletableFuture cfBinary; CompletableFuture cfPing; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingBinaryPingClose(boolean last) throws Exception { repeatable(() -> { server = Support.notReadingServer(); diff --git a/test/jdk/java/net/httpclient/websocket/PendingBinaryPongClose.java b/test/jdk/java/net/httpclient/websocket/PendingBinaryPongClose.java index bef3d258850..a8330faeb3f 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingBinaryPongClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingBinaryPongClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,28 +24,30 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.sendBufferSize=8192 * -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.websocket.debug=true * PendingBinaryPongClose */ -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingBinaryPongClose extends PendingOperations { CompletableFuture cfBinary; CompletableFuture cfPong; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingBinaryPongClose(boolean last) throws Exception { repeatable(() -> { server = Support.notReadingServer(); diff --git a/test/jdk/java/net/httpclient/websocket/PendingOperations.java b/test/jdk/java/net/httpclient/websocket/PendingOperations.java index b4d7d7e2222..32350a1ab41 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingOperations.java +++ b/test/jdk/java/net/httpclient/websocket/PendingOperations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,9 +21,6 @@ * questions. */ -import org.testng.annotations.AfterMethod; -import org.testng.annotations.DataProvider; - import java.io.IOException; import java.net.http.HttpClient; import java.net.http.WebSocket; @@ -35,6 +32,8 @@ import java.util.function.BooleanSupplier; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.newBuilder; +import org.junit.jupiter.api.AfterEach; + /* Common infrastructure for tests that check pending operations */ public class PendingOperations { @@ -54,7 +53,7 @@ public class PendingOperations { return newBuilder().proxy(NO_PROXY).build(); } - @AfterMethod + @AfterEach public void cleanup() { // make sure we have a trace both on System.out and System.err // to help with diagnosis. @@ -85,8 +84,7 @@ public class PendingOperations { Support.assertNotDone(future); } - @DataProvider(name = "booleans") - public Object[][] booleans() { + public static Object[][] booleans() { return new Object[][]{{Boolean.TRUE}, {Boolean.FALSE}}; } diff --git a/test/jdk/java/net/httpclient/websocket/PendingPingBinaryClose.java b/test/jdk/java/net/httpclient/websocket/PendingPingBinaryClose.java index c1c314395e8..e07ebe0d03a 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingPingBinaryClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingPingBinaryClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.sendBufferSize=8192 * PendingPingBinaryClose */ @@ -33,21 +33,23 @@ // * -Djdk.internal.httpclient.debug=true // * -Djdk.internal.httpclient.websocket.debug=true -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingPingBinaryClose extends PendingOperations { CompletableFuture cfBinary; CompletableFuture cfPing; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingPingBinaryClose(boolean last) throws Exception { repeatable( () -> { server = Support.notReadingServer(); diff --git a/test/jdk/java/net/httpclient/websocket/PendingPingTextClose.java b/test/jdk/java/net/httpclient/websocket/PendingPingTextClose.java index 82666fafe67..eae01f804a4 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingPingTextClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingPingTextClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.sendBufferSize=8192 * PendingPingTextClose */ @@ -33,14 +33,15 @@ // * -Djdk.internal.httpclient.debug=true // * -Djdk.internal.httpclient.websocket.debug=true -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingPingTextClose extends PendingOperations { static boolean debug = false; // avoid too verbose output @@ -48,7 +49,8 @@ public class PendingPingTextClose extends PendingOperations { CompletableFuture cfPing; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingPingTextClose(boolean last) throws Exception { try { repeatable(() -> { diff --git a/test/jdk/java/net/httpclient/websocket/PendingPongBinaryClose.java b/test/jdk/java/net/httpclient/websocket/PendingPongBinaryClose.java index 0aa2f24c660..32640853b00 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingPongBinaryClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingPongBinaryClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.sendBufferSize=8192 * PendingPongBinaryClose */ @@ -33,21 +33,23 @@ // * -Djdk.internal.httpclient.debug=true // * -Djdk.internal.httpclient.websocket.debug=true -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingPongBinaryClose extends PendingOperations { CompletableFuture cfBinary; CompletableFuture cfPong; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingPongBinaryClose(boolean last) throws Exception { repeatable( () -> { server = Support.notReadingServer(); diff --git a/test/jdk/java/net/httpclient/websocket/PendingPongTextClose.java b/test/jdk/java/net/httpclient/websocket/PendingPongTextClose.java index f919a6706ad..f4d6c84c2f5 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingPongTextClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingPongTextClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.httpclient.sendBufferSize=8192 * PendingPongTextClose */ @@ -33,21 +33,23 @@ // * -Djdk.internal.httpclient.debug=true // * -Djdk.internal.httpclient.websocket.debug=true -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingPongTextClose extends PendingOperations { CompletableFuture cfText; CompletableFuture cfPong; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingPongTextClose(boolean last) throws Exception { repeatable( () -> { server = Support.notReadingServer(); diff --git a/test/jdk/java/net/httpclient/websocket/PendingTextPingClose.java b/test/jdk/java/net/httpclient/websocket/PendingTextPingClose.java index 39c8bbdc444..76f12430804 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingTextPingClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingTextPingClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,13 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.websocket.debug=true * -Djdk.httpclient.sendBufferSize=8192 * PendingTextPingClose */ -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -40,13 +38,17 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingTextPingClose extends PendingOperations { CompletableFuture cfText; CompletableFuture cfPing; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingTextPingClose(boolean last) throws Exception { repeatable(() -> { server = Support.notReadingServer(); diff --git a/test/jdk/java/net/httpclient/websocket/PendingTextPongClose.java b/test/jdk/java/net/httpclient/websocket/PendingTextPongClose.java index 8fa90400760..a2a41a73d7b 100644 --- a/test/jdk/java/net/httpclient/websocket/PendingTextPongClose.java +++ b/test/jdk/java/net/httpclient/websocket/PendingTextPongClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,15 +24,13 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.websocket.debug=true * -Djdk.httpclient.sendBufferSize=8192 * PendingTextPongClose */ -import org.testng.annotations.Test; - import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -40,13 +38,17 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + public class PendingTextPongClose extends PendingOperations { CompletableFuture cfText; CompletableFuture cfPong; CompletableFuture cfClose; - @Test(dataProvider = "booleans") + @ParameterizedTest + @MethodSource("booleans") public void pendingTextPongClose(boolean last) throws Exception { repeatable(() -> { server = Support.notReadingServer(); diff --git a/test/jdk/java/net/httpclient/websocket/ReaderDriver.java b/test/jdk/java/net/httpclient/websocket/ReaderDriver.java index 0b874792b4f..3e195be046d 100644 --- a/test/jdk/java/net/httpclient/websocket/ReaderDriver.java +++ b/test/jdk/java/net/httpclient/websocket/ReaderDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ * @test * @bug 8159053 * @modules java.net.http/jdk.internal.net.http.websocket:open - * @run testng/othervm/timeout=240 --add-reads java.net.http=ALL-UNNAMED java.net.http/jdk.internal.net.http.websocket.ReaderTest + * @run junit/othervm/timeout=240 + * --add-reads java.net.http=ALL-UNNAMED + * java.net.http/jdk.internal.net.http.websocket.ReaderTest */ public final class ReaderDriver { } diff --git a/test/jdk/java/net/httpclient/websocket/SecureSupport.java b/test/jdk/java/net/httpclient/websocket/SecureSupport.java index 8b565768c29..41709d2fedb 100644 --- a/test/jdk/java/net/httpclient/websocket/SecureSupport.java +++ b/test/jdk/java/net/httpclient/websocket/SecureSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,18 +22,9 @@ */ import java.io.IOException; -import java.net.Socket; import java.nio.ByteBuffer; -import java.nio.channels.SocketChannel; import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static org.testng.Assert.assertThrows; /** * Helper class to create instances of DummySecureWebSocketServer which diff --git a/test/jdk/java/net/httpclient/websocket/SendTest.java b/test/jdk/java/net/httpclient/websocket/SendTest.java index 39021131156..b3a433b5c29 100644 --- a/test/jdk/java/net/httpclient/websocket/SendTest.java +++ b/test/jdk/java/net/httpclient/websocket/SendTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,22 +24,22 @@ /* * @test * @build DummyWebSocketServer - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.websocket.debug=true * SendTest */ -import org.testng.annotations.Test; - import java.io.IOException; import java.net.http.WebSocket; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.newBuilder; import static java.net.http.WebSocket.NORMAL_CLOSURE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class SendTest { @@ -90,7 +90,7 @@ public class SendTest { try { webSocket.sendClose(NORMAL_CLOSURE, "").join(); assertTrue(webSocket.isOutputClosed()); - assertEquals(webSocket.getSubprotocol(), ""); + assertEquals("", webSocket.getSubprotocol()); webSocket.request(1); // No exceptions must be thrown } finally { webSocket.abort(); diff --git a/test/jdk/java/net/httpclient/websocket/Support.java b/test/jdk/java/net/httpclient/websocket/Support.java index 1323ae35105..73f840ff7eb 100644 --- a/test/jdk/java/net/httpclient/websocket/Support.java +++ b/test/jdk/java/net/httpclient/websocket/Support.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,8 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertFalse; public class Support { diff --git a/test/jdk/java/net/httpclient/websocket/WSHandshakeExceptionTest.java b/test/jdk/java/net/httpclient/websocket/WSHandshakeExceptionTest.java index 90db79dc8ef..f28d84b2f20 100644 --- a/test/jdk/java/net/httpclient/websocket/WSHandshakeExceptionTest.java +++ b/test/jdk/java/net/httpclient/websocket/WSHandshakeExceptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.TestServerConfigurator * @modules java.net.http/jdk.internal.net.http.common * jdk.httpserver - * @run testng/othervm -Djdk.internal.httpclient.debug=true WSHandshakeExceptionTest + * @run junit/othervm -Djdk.internal.httpclient.debug=true WSHandshakeExceptionTest */ import com.sun.net.httpserver.HttpHandler; @@ -37,8 +37,6 @@ import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.HttpsServer; import com.sun.net.httpserver.HttpExchange; - - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -49,10 +47,6 @@ import java.net.http.WebSocketHandshakeException; import jdk.httpclient.test.lib.common.TestServerConfigurator; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.net.InetSocketAddress; import java.net.URI; @@ -62,29 +56,33 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static java.net.http.HttpClient.Builder.NO_PROXY; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; import static java.lang.System.out; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + public class WSHandshakeExceptionTest { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - HttpServer httpTestServer; // HTTP/1.1 [ 2 servers ] - HttpsServer httpsTestServer; // HTTPS/1.1 - String httpURI; - String httpsURI; - String httpNonUtf8URI; - String httpsNonUtf8URI; - HttpClient sharedClient; + private static HttpServer httpTestServer; // HTTP/1.1 [ 2 servers ] + private static HttpsServer httpsTestServer; // HTTPS/1.1 + private static String httpURI; + private static String httpsURI; + private static String httpNonUtf8URI; + private static String httpsNonUtf8URI; + private static HttpClient sharedClient; static final int ITERATION_COUNT = 4; // a shared executor helps reduce the amount of threads created by the test static final ExecutorService executor = Executors.newCachedThreadPool(); - @DataProvider(name = "variants") - public Object[][] variants() { + public static Object[][] variants() { return new Object[][]{ { httpURI, false }, { httpsURI, false }, @@ -106,7 +104,8 @@ public class WSHandshakeExceptionTest { .build(); } - @Test(dataProvider = "variants") + @ParameterizedTest + @MethodSource("variants") public void test(String uri, boolean sameClient) { HttpClient client = sharedClient; boolean pause; @@ -132,7 +131,7 @@ public class WSHandshakeExceptionTest { WebSocketHandshakeException wse = (WebSocketHandshakeException) t; assertNotNull(wse.getResponse()); assertNotNull(wse.getResponse().body()); - assertEquals(wse.getResponse().body().getClass(), String.class); + assertEquals(String.class, wse.getResponse().body().getClass()); String body = (String)wse.getResponse().body(); out.println("Status code is " + wse.getResponse().statusCode()); out.println("Response is " + body); @@ -145,7 +144,7 @@ public class WSHandshakeExceptionTest { // default HttpServer 404 body expected assertTrue(body.contains("404")); } - assertEquals(wse.getResponse().statusCode(), 404); + assertEquals(404, wse.getResponse().statusCode()); } } } @@ -159,8 +158,8 @@ public class WSHandshakeExceptionTest { } } - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { // HTTP/1.1 InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); httpTestServer = HttpServer.create(sa, 0); @@ -178,8 +177,8 @@ public class WSHandshakeExceptionTest { httpsTestServer.start(); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { sharedClient = null; gc(100); httpTestServer.stop(0); diff --git a/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java b/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java index b28b8f59875..beef8cb42a4 100644 --- a/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java +++ b/test/jdk/java/net/httpclient/websocket/WebSocketBuilderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,9 @@ * @bug 8159053 * @build DummyWebSocketServer * Support - * @run testng/othervm WebSocketBuilderTest + * @run junit/othervm WebSocketBuilderTest */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - import java.net.URI; import java.net.http.HttpClient; import java.net.http.WebSocket; @@ -42,7 +39,10 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.testng.Assert.assertThrows; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * In some places in this test a new String is created out of a string literal. @@ -98,7 +98,8 @@ public final class WebSocketBuilderTest { .connectTimeout(null)); } - @Test(dataProvider = "badURIs") + @ParameterizedTest + @MethodSource("badURIs") void illegalURI(URI uri) { WebSocket.Builder b = HttpClient.newHttpClient().newWebSocketBuilder(); assertFails(IllegalArgumentException.class, @@ -129,7 +130,8 @@ public final class WebSocketBuilderTest { // TODO: test for bad syntax headers // TODO: test for overwrites (subprotocols) and additions (headers) - @Test(dataProvider = "badSubprotocols") + @ParameterizedTest + @MethodSource("badSubprotocols") public void illegalSubprotocolsSyntax(String s) { WebSocket.Builder b = HttpClient.newHttpClient() .newWebSocketBuilder() @@ -138,7 +140,8 @@ public final class WebSocketBuilderTest { b.buildAsync(VALID_URI, listener())); } - @Test(dataProvider = "duplicatingSubprotocols") + @ParameterizedTest + @MethodSource("duplicatingSubprotocols") public void illegalSubprotocolsDuplicates(String mostPreferred, String[] lesserPreferred) { WebSocket.Builder b = HttpClient.newHttpClient() @@ -148,7 +151,8 @@ public final class WebSocketBuilderTest { b.buildAsync(VALID_URI, listener())); } - @Test(dataProvider = "badConnectTimeouts") + @ParameterizedTest + @MethodSource("badConnectTimeouts") public void illegalConnectTimeout(Duration d) { WebSocket.Builder b = HttpClient.newHttpClient() .newWebSocketBuilder() @@ -157,8 +161,7 @@ public final class WebSocketBuilderTest { b.buildAsync(VALID_URI, listener())); } - @DataProvider - public Object[][] badURIs() { + public static Object[][] badURIs() { return new Object[][]{ {URI.create("http://example.com")}, {URI.create("ftp://example.com")}, @@ -167,8 +170,7 @@ public final class WebSocketBuilderTest { }; } - @DataProvider - public Object[][] badConnectTimeouts() { + public static Object[][] badConnectTimeouts() { return new Object[][]{ {Duration.ofDays(0)}, {Duration.ofDays(-1)}, @@ -188,7 +190,6 @@ public final class WebSocketBuilderTest { // https://tools.ietf.org/html/rfc7230#section-3.2.6 // https://tools.ietf.org/html/rfc20 - @DataProvider public static Object[][] badSubprotocols() { return new Object[][]{ {""}, @@ -215,7 +216,6 @@ public final class WebSocketBuilderTest { }; } - @DataProvider public static Object[][] duplicatingSubprotocols() { return new Object[][]{ {"a.b.c", new String[]{"a.b.c"}}, diff --git a/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java b/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java index 0099104e872..56474555235 100644 --- a/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java +++ b/test/jdk/java/net/httpclient/websocket/WebSocketExtendedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @bug 8159053 - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.websocket.debug=true * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.websocket.writeBufferSize=1024 @@ -32,8 +32,6 @@ */ import jdk.internal.net.http.websocket.Frame; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.IOException; import java.net.http.WebSocket; @@ -43,8 +41,11 @@ import java.util.List; import java.util.Random; import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpClient.newBuilder; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /* @@ -52,7 +53,7 @@ import static org.testng.Assert.assertTrue; * possible fragmentation. */ public class WebSocketExtendedTest { -// * run testng/othervm +// * run junit/othervm // * -Djdk.httpclient.websocket.writeBufferSize=16 // * -Djdk.httpclient.sendBufferSize=32 WebSocketTextTest @@ -65,7 +66,8 @@ public class WebSocketExtendedTest { // FIXME ensure subsequent (sendText/Binary, false) only CONTINUATIONs - @Test(dataProvider = "binary") + @ParameterizedTest + @MethodSource("binary") public void binary(ByteBuffer expected) throws IOException, InterruptedException { try (DummyWebSocketServer server = new DummyWebSocketServer()) { server.open(); @@ -76,15 +78,16 @@ public class WebSocketExtendedTest { ws.sendBinary(expected.duplicate(), true).join(); ws.abort(); List frames = server.readFrames(); - assertEquals(frames.size(), 1); + assertEquals(1, frames.size()); DummyWebSocketServer.DecodedFrame f = frames.get(0); assertTrue(f.last()); - assertEquals(f.opcode(), Frame.Opcode.BINARY); - assertEquals(f.data(), expected); + assertEquals(Frame.Opcode.BINARY, f.opcode()); + assertEquals(expected, f.data()); } } - @Test(dataProvider = "pingPong") + @ParameterizedTest + @MethodSource("pingPongSizes") public void ping(ByteBuffer expected) throws Exception { try (DummyWebSocketServer server = new DummyWebSocketServer()) { server.open(); @@ -95,17 +98,18 @@ public class WebSocketExtendedTest { ws.sendPing(expected.duplicate()).join(); ws.abort(); List frames = server.readFrames(); - assertEquals(frames.size(), 1); + assertEquals(1, frames.size()); DummyWebSocketServer.DecodedFrame f = frames.get(0); - assertEquals(f.opcode(), Frame.Opcode.PING); + assertEquals(Frame.Opcode.PING, f.opcode()); ByteBuffer actual = ByteBuffer.allocate(expected.remaining()); actual.put(f.data()); actual.flip(); - assertEquals(actual, expected); + assertEquals(expected, actual); } } - @Test(dataProvider = "pingPong") + @ParameterizedTest + @MethodSource("pingPongSizes") public void pong(ByteBuffer expected) throws Exception { try (DummyWebSocketServer server = new DummyWebSocketServer()) { server.open(); @@ -116,17 +120,18 @@ public class WebSocketExtendedTest { ws.sendPong(expected.duplicate()).join(); ws.abort(); List frames = server.readFrames(); - assertEquals(frames.size(), 1); + assertEquals(1, frames.size()); DummyWebSocketServer.DecodedFrame f = frames.get(0); - assertEquals(f.opcode(), Frame.Opcode.PONG); + assertEquals(Frame.Opcode.PONG, f.opcode()); ByteBuffer actual = ByteBuffer.allocate(expected.remaining()); actual.put(f.data()); actual.flip(); - assertEquals(actual, expected); + assertEquals(expected, actual); } } - @Test(dataProvider = "close") + @ParameterizedTest + @MethodSource("closeArguments") public void close(int statusCode, String reason) throws Exception { try (DummyWebSocketServer server = new DummyWebSocketServer()) { server.open(); @@ -137,18 +142,19 @@ public class WebSocketExtendedTest { ws.sendClose(statusCode, reason).join(); ws.abort(); List frames = server.readFrames(); - assertEquals(frames.size(), 1); + assertEquals(1, frames.size()); DummyWebSocketServer.DecodedFrame f = frames.get(0); - assertEquals(f.opcode(), Frame.Opcode.CLOSE); + assertEquals(Frame.Opcode.CLOSE, f.opcode()); ByteBuffer actual = ByteBuffer.allocate(Frame.MAX_CONTROL_FRAME_PAYLOAD_LENGTH); actual.put(f.data()); actual.flip(); - assertEquals(actual.getChar(), statusCode); - assertEquals(StandardCharsets.UTF_8.decode(actual).toString(), reason); + assertEquals(statusCode, actual.getChar()); + assertEquals(reason, StandardCharsets.UTF_8.decode(actual).toString()); } } - @Test(dataProvider = "text") + @ParameterizedTest + @MethodSource("texts") public void text(String expected) throws Exception { try (DummyWebSocketServer server = new DummyWebSocketServer()) { server.open(); @@ -163,12 +169,11 @@ public class WebSocketExtendedTest { ByteBuffer actual = ByteBuffer.allocate(maxBytes); frames.stream().forEachOrdered(f -> actual.put(f.data())); actual.flip(); - assertEquals(StandardCharsets.UTF_8.decode(actual).toString(), expected); + assertEquals(expected, StandardCharsets.UTF_8.decode(actual).toString()); } } - @DataProvider(name = "pingPong") - public Object[][] pingPongSizes() { + public static Object[][] pingPongSizes() { return new Object[][]{ {bytes( 0)}, {bytes( 1)}, @@ -177,8 +182,7 @@ public class WebSocketExtendedTest { }; } - @DataProvider(name = "close") - public Object[][] closeArguments() { + public static Object[][] closeArguments() { return new Object[][]{ {WebSocket.NORMAL_CLOSURE, utf8String( 0)}, {WebSocket.NORMAL_CLOSURE, utf8String( 1)}, @@ -216,16 +220,14 @@ public class WebSocketExtendedTest { return str.toString(); } - @DataProvider(name = "text") - public Object[][] texts() { + public static Object[][] texts() { return new Object[][]{ {utf8String( 0)}, {utf8String(1024)}, }; } - @DataProvider(name = "binary") - public Object[][] binary() { + public static Object[][] binary() { return new Object[][]{ {bytes( 0)}, {bytes(1024)}, diff --git a/test/jdk/java/net/httpclient/websocket/WebSocketProxyTest.java b/test/jdk/java/net/httpclient/websocket/WebSocketProxyTest.java index 46758b2fe6e..a410aa9fe75 100644 --- a/test/jdk/java/net/httpclient/websocket/WebSocketProxyTest.java +++ b/test/jdk/java/net/httpclient/websocket/WebSocketProxyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * @library /test/lib * @compile SecureSupport.java DummySecureWebSocketServer.java ../ProxyServer.java * @build jdk.test.lib.net.SimpleSSLContext WebSocketProxyTest - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.websocket.debug=true * -Djdk.httpclient.HttpClient.log=errors,requests,headers @@ -61,16 +61,18 @@ import java.util.function.Supplier; import java.util.stream.Collectors; import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import static java.net.http.HttpClient.newBuilder; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.testng.Assert.assertEquals; -import static org.testng.FileAssert.fail; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class WebSocketProxyTest { @@ -132,8 +134,7 @@ public class WebSocketProxyTest { @Override public String toString() { return "AUTH_TUNNELING_PROXY_SERVER"; } }; - @DataProvider(name = "servers") - public Object[][] servers() { + public static Object[][] servers() { return new Object[][] { { SERVER_WITH_CANNED_DATA, TUNNELING_PROXY_SERVER }, { SERVER_WITH_CANNED_DATA, AUTH_TUNNELING_PROXY_SERVER }, @@ -175,7 +176,8 @@ public class WebSocketProxyTest { return "%s and %s %s".formatted(actual, expected, message); } - @Test(dataProvider = "servers") + @ParameterizedTest + @MethodSource("servers") public void simpleAggregatingBinaryMessages (Function serverSupplier, Supplier proxyServerSupplier) @@ -263,7 +265,7 @@ public class WebSocketProxyTest { .join(); List a = actual.join(); - assertEquals(ofBytes(a), ofBytes(expected), diagnose(a, expected)); + assertEquals(ofBytes(expected), ofBytes(a), diagnose(a, expected)); } } @@ -359,7 +361,7 @@ public class WebSocketProxyTest { } catch (CompletionException expected) { WebSocketHandshakeException e = (WebSocketHandshakeException)expected.getCause(); HttpResponse response = e.getResponse(); - assertEquals(response.statusCode(), 407); + assertEquals(407, response.statusCode()); } } } @@ -398,7 +400,7 @@ public class WebSocketProxyTest { } } - @BeforeMethod + @BeforeEach public void breakBetweenTests() { System.gc(); try {Thread.sleep(100); } catch (InterruptedException x) { /* OK */ } diff --git a/test/jdk/java/net/httpclient/websocket/WebSocketTest.java b/test/jdk/java/net/httpclient/websocket/WebSocketTest.java index 43bcb054b7d..2b1df3d7e87 100644 --- a/test/jdk/java/net/httpclient/websocket/WebSocketTest.java +++ b/test/jdk/java/net/httpclient/websocket/WebSocketTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,10 @@ * @library ../access * @build DummyWebSocketServer * java.net.http/jdk.internal.net.http.HttpClientTimerAccess - * @run testng/othervm + * @run junit/othervm * WebSocketTest */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.IOException; import java.net.Authenticator; @@ -63,9 +61,13 @@ import static java.net.http.HttpClient.newBuilder; import static java.net.http.WebSocket.NORMAL_CLOSURE; import static java.nio.charset.StandardCharsets.UTF_8; import static jdk.internal.net.http.HttpClientTimerAccess.assertNoResponseTimerEventRegistrations; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; public class WebSocketTest { @@ -264,8 +266,7 @@ public class WebSocketTest { } } - @DataProvider(name = "sequence") - public Object[][] data1() { + public static Object[][] data1() { int[] CLOSE = { 0x81, 0x00, // "" 0x82, 0x00, // [] @@ -292,7 +293,8 @@ public class WebSocketTest { }; } - @Test(dataProvider = "sequence") + @ParameterizedTest + @MethodSource("data1") public void listenerSequentialOrder(int[] binary, long requestSize) throws IOException { @@ -470,8 +472,7 @@ public class WebSocketTest { @Override public String toString() { return "AUTH_SERVER_WITH_CANNED_DATA"; } }; - @DataProvider(name = "servers") - public Object[][] servers() { + public static Object[][] servers() { return new Object[][] { { SERVER_WITH_CANNED_DATA }, { AUTH_SERVER_WITH_CANNED_DATA }, @@ -507,7 +508,8 @@ public class WebSocketTest { return "%s and %s %s".formatted(actual, expected, message); } - @Test(dataProvider = "servers") + @ParameterizedTest + @MethodSource("servers") public void simpleAggregatingBinaryMessages (Function serverSupplier) throws IOException @@ -600,14 +602,15 @@ public class WebSocketTest { .join(); try { List a = actual.join(); - assertEquals(ofBytes(a), ofBytes(expected), diagnose(a, expected)); + assertEquals(ofBytes(expected), ofBytes(a), diagnose(a, expected)); } finally { webSocket.abort(); } } } - @Test(dataProvider = "servers") + @ParameterizedTest + @MethodSource("servers") public void simpleAggregatingTextMessages (Function serverSupplier) throws IOException @@ -683,7 +686,7 @@ public class WebSocketTest { .join(); try { List a = actual.join(); - assertEquals(a, expected); + assertEquals(expected, a); } finally { webSocket.abort(); } @@ -694,7 +697,8 @@ public class WebSocketTest { * Exercises the scenario where requests for more messages are made prior to * completing the returned CompletionStage instances. */ - @Test(dataProvider = "servers") + @ParameterizedTest + @MethodSource("servers") public void aggregatingTextMessages (Function serverSupplier) throws IOException @@ -784,7 +788,7 @@ public class WebSocketTest { .join(); try { List a = actual.join(); - assertEquals(a, expected); + assertEquals(expected, a); } finally { webSocket.abort(); } @@ -853,7 +857,7 @@ public class WebSocketTest { } catch (CompletionException expected) { WebSocketHandshakeException e = (WebSocketHandshakeException)expected.getCause(); HttpResponse response = e.getResponse(); - assertEquals(response.statusCode(), 401); + assertEquals(401, response.statusCode()); } } } diff --git a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/HeaderWriterTest.java b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/HeaderWriterTest.java index 0e55eaf521f..59a66591c93 100644 --- a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/HeaderWriterTest.java +++ b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/HeaderWriterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ package jdk.internal.net.http.websocket; -import org.testng.annotations.Test; import jdk.internal.net.http.websocket.Frame.HeaderWriter; import jdk.internal.net.http.websocket.Frame.Opcode; @@ -32,10 +31,12 @@ import java.util.OptionalInt; import static java.util.OptionalInt.empty; import static java.util.OptionalInt.of; -import static org.testng.Assert.assertEquals; import static jdk.internal.net.http.websocket.TestSupport.assertThrows; import static jdk.internal.net.http.websocket.TestSupport.forEachPermutation; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class HeaderWriterTest { private long cases, frames; @@ -109,7 +110,7 @@ public class HeaderWriterTest { ByteBuffer actual = ByteBuffer.allocate(Frame.MAX_HEADER_SIZE_BYTES + 2); writer.write(actual); actual.flip(); - assertEquals(actual, expected); + assertEquals(expected, actual); }); } } diff --git a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java index 7eb892f12ea..cb59b9f7213 100644 --- a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java +++ b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MaskerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,17 +23,17 @@ package jdk.internal.net.http.websocket; -import org.testng.annotations.Test; - import java.nio.ByteBuffer; import java.security.SecureRandom; import java.util.stream.IntStream; -import static org.testng.Assert.assertEquals; import static jdk.internal.net.http.websocket.Frame.Masker.applyMask; import static jdk.internal.net.http.websocket.TestSupport.forEachBufferPartition; import static jdk.internal.net.http.websocket.TestSupport.fullCopy; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class MaskerTest { private static final SecureRandom random = new SecureRandom(); @@ -98,14 +98,14 @@ public class MaskerTest { int dstRemaining = dstCopy.remaining(); int masked = Math.min(srcRemaining, dstRemaining); // 1. position check - assertEquals(src.position(), srcCopy.position() + masked); - assertEquals(dst.position(), dstCopy.position() + masked); + assertEquals(srcCopy.position() + masked, src.position()); + assertEquals(dstCopy.position() + masked, dst.position()); // 2. masking check src.position(srcCopy.position()); dst.position(dstCopy.position()); for (; src.hasRemaining() && dst.hasRemaining(); offset = (offset + 1) & 3) { - assertEquals(dst.get(), src.get() ^ maskBytes[offset]); + assertEquals(src.get() ^ maskBytes[offset], dst.get()); } // 3. corruption check // 3.1 src contents haven't changed @@ -113,7 +113,7 @@ public class MaskerTest { int srcLimit = src.limit(); src.clear(); srcCopy.clear(); - assertEquals(src, srcCopy); + assertEquals(srcCopy, src); src.limit(srcLimit).position(srcPosition); // restore src // 3.2 dst leading and trailing regions' contents haven't changed int dstPosition = dst.position(); @@ -122,11 +122,11 @@ public class MaskerTest { // leading dst.position(0).limit(dstInitialPosition); dstCopy.position(0).limit(dstInitialPosition); - assertEquals(dst, dstCopy); + assertEquals(dstCopy, dst); // trailing dst.limit(dst.capacity()).position(dstLimit); dstCopy.limit(dst.capacity()).position(dstLimit); - assertEquals(dst, dstCopy); + assertEquals(dstCopy, dst); // restore dst dst.position(dstPosition).limit(dstLimit); return offset; diff --git a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MessageQueueTest.java b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MessageQueueTest.java index 61503f0e235..73cab76df28 100644 --- a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MessageQueueTest.java +++ b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/MessageQueueTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,6 @@ package jdk.internal.net.http.websocket; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -46,10 +43,14 @@ import java.util.function.BiConsumer; import java.util.function.Supplier; import static jdk.internal.net.http.websocket.MessageQueue.effectiveCapacityOf; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertTrue; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * A unit test for MessageQueue. The test is aware of the details of the queue @@ -59,7 +60,6 @@ public class MessageQueueTest { private static final Random r = new SecureRandom(); - @DataProvider(name = "illegalCapacities") public static Object[][] illegalCapacities() { return new Object[][]{ new Object[]{Integer.MIN_VALUE}, @@ -69,17 +69,20 @@ public class MessageQueueTest { }; } - @Test(dataProvider = "illegalCapacities") + @ParameterizedTest + @MethodSource("illegalCapacities") public void illegalCapacity(int n) { assertThrows(IllegalArgumentException.class, () -> new MessageQueue(n)); } - @Test(dataProvider = "capacities") + @ParameterizedTest + @MethodSource("capacities") public void emptiness(int n) { assertTrue(new MessageQueue(n).isEmpty()); } - @Test(dataProvider = "capacities") + @ParameterizedTest + @MethodSource("capacities") public void fullness(int n) throws IOException { MessageQueue q = new MessageQueue(n); int cap = effectiveCapacityOf(n); @@ -97,7 +100,7 @@ public class MessageQueueTest { for (int i = 0; i < cap; i++) { Message expected = referenceQueue.remove(); Message actual = new Remover().removeFrom(q); - assertEquals(actual, expected); + assertEquals(expected, actual); } } @@ -144,7 +147,8 @@ public class MessageQueueTest { action, future); } - @Test(dataProvider = "capacities") + @ParameterizedTest + @MethodSource("capacities") public void caterpillarWalk(int n) throws IOException { // System.out.println("n: " + n); int cap = effectiveCapacityOf(n); @@ -164,7 +168,7 @@ public class MessageQueueTest { for (int i = 0; i < p; i++) { Message expected = referenceQueue.remove(); Message actual = remover.removeFrom(q); - assertEquals(actual, expected); + assertEquals(expected, actual); } assertTrue(q.isEmpty()); } @@ -243,7 +247,7 @@ public class MessageQueueTest { f.get(); // Just to check for exceptions } consumer.get(); // Waiting for consumer to collect all the messages - assertEquals(actualList.size(), expectedList.size()); + assertEquals(expectedList.size(), actualList.size()); for (Message m : expectedList) { assertTrue(actualList.remove(m)); } @@ -257,7 +261,8 @@ public class MessageQueueTest { } } - @Test(dataProvider = "capacities") + @ParameterizedTest + @MethodSource("capacities") public void testSingleThreaded(int n) throws IOException { Queue referenceQueue = new LinkedList<>(); MessageQueue q = new MessageQueue(n); @@ -271,13 +276,12 @@ public class MessageQueueTest { for (int i = 0; i < cap; i++) { Message expected = referenceQueue.remove(); Message actual = new Remover().removeFrom(q); - assertEquals(actual, expected); + assertEquals(expected, actual); } assertTrue(q.isEmpty()); } - @DataProvider(name = "capacities") - public Object[][] capacities() { + public static Object[][] capacities() { return new Object[][]{ new Object[]{ 1}, new Object[]{ 2}, diff --git a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/ReaderTest.java b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/ReaderTest.java index c53ac88f69c..c7b1ab80fbd 100644 --- a/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/ReaderTest.java +++ b/test/jdk/java/net/httpclient/websocket/java.net.http/jdk/internal/net/http/websocket/ReaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ package jdk.internal.net.http.websocket; -import org.testng.annotations.Test; import jdk.internal.net.http.websocket.Frame.Opcode; import java.nio.ByteBuffer; @@ -35,10 +34,12 @@ import java.util.function.IntUnaryOperator; import static java.util.OptionalInt.empty; import static java.util.OptionalInt.of; -import static org.testng.Assert.assertEquals; import static jdk.internal.net.http.websocket.TestSupport.assertThrows; import static jdk.internal.net.http.websocket.TestSupport.forEachBufferPartition; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ReaderTest { private long cases, frames; @@ -128,15 +129,15 @@ public class ReaderTest { for (ByteBuffer b : buffers) { r.readFrame(b, c); } - assertEquals(fin, c.fin()); - assertEquals(rsv1, c.rsv1()); - assertEquals(rsv2, c.rsv2()); - assertEquals(rsv3, c.rsv3()); - assertEquals(opcode, c.opcode()); - assertEquals(mask.isPresent(), c.mask()); - assertEquals(payloadLen, c.payloadLen()); - assertEquals(mask, c.maskingKey()); - assertEquals(payloadLen == 0, c.isEndFrame()); + assertEquals(c.fin(), fin); + assertEquals(c.rsv1(), rsv1); + assertEquals(c.rsv2(), rsv2); + assertEquals(c.rsv3(), rsv3); + assertEquals(c.opcode(), opcode); + assertEquals(c.mask(), mask.isPresent()); + assertEquals(c.payloadLen(), payloadLen); + assertEquals(c.maskingKey(), mask); + assertEquals(c.isEndFrame(), payloadLen == 0); }); } diff --git a/test/jdk/java/net/httpclient/websocket/security/WSSanityTest.java b/test/jdk/java/net/httpclient/websocket/security/WSSanityTest.java index 787486dbd84..c8e4faa1ad3 100644 --- a/test/jdk/java/net/httpclient/websocket/security/WSSanityTest.java +++ b/test/jdk/java/net/httpclient/websocket/security/WSSanityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @summary Basic sanity checks for WebSocket URI from the Builder * @compile ../DummyWebSocketServer.java ../../ProxyServer.java - * @run testng/othervm WSSanityTest + * @run junit/othervm WSSanityTest */ import java.io.IOException; @@ -38,20 +38,21 @@ import java.net.URI; import java.util.List; import java.net.http.HttpClient; import java.net.http.WebSocket; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; public class WSSanityTest { - URI wsURI; - DummyWebSocketServer webSocketServer; - InetSocketAddress proxyAddress; + private static URI wsURI; + private static DummyWebSocketServer webSocketServer; + private static InetSocketAddress proxyAddress; - @BeforeTest - public void setup() throws Exception { + @BeforeAll + public static void setup() throws Exception { ProxyServer proxyServer = new ProxyServer(0, true); proxyAddress = new InetSocketAddress(InetAddress.getLoopbackAddress(), proxyServer.getPort()); @@ -63,8 +64,8 @@ public class WSSanityTest { System.out.println("DummyWebSocketServer: " + wsURI); } - @AfterTest - public void teardown() { + @AfterAll + public static void teardown() { webSocketServer.close(); } @@ -75,8 +76,7 @@ public class WSSanityTest { T run() throws Exception; } - @DataProvider(name = "passingScenarios") - public Object[][] passingScenarios() { + public static Object[][] passingScenarios() { HttpClient noProxyClient = HttpClient.newHttpClient(); return new Object[][]{ { (ExceptionAction)() -> { @@ -146,14 +146,15 @@ public class WSSanityTest { HttpClient client = HttpClient.newBuilder().proxy(ps).build(); client.newWebSocketBuilder() .buildAsync(wsURI, noOpListener).get().abort(); - assertEquals(ps.count(), 1); // ps.select only invoked once + assertEquals(1, ps.count()); // ps.select only invoked once return null; }, "7" }, }; } - @Test(dataProvider = "passingScenarios") + @ParameterizedTest + @MethodSource("passingScenarios") public void testScenarios(ExceptionAction action, String dataProviderId) throws Exception { From 0668dab54568a08d49c8c10a7efc4d06ca191083 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Thu, 5 Mar 2026 12:26:37 +0000 Subject: [PATCH 074/170] 8379114: HttpServer path prefix matching incorrectly matches paths that are not slash-prefixed Reviewed-by: dfuchs --- .../sun/net/httpserver/ContextList.java | 51 +++---- .../ContextPathMatcherPathPrefixTest.java | 139 +++++++++++++++--- .../ContextPathMatcherStringPrefixTest.java | 40 ++--- 3 files changed, 162 insertions(+), 68 deletions(-) diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java index 6393ca34798..14a07b3a677 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java @@ -186,38 +186,31 @@ class ContextList { */ PATH_PREFIX((contextPath, requestPath) -> { - // Fast-path for `/` - if ("/".equals(contextPath)) { + // Does the request path prefix match? + if (!requestPath.startsWith(contextPath)) { + return false; + } + + // Is it an exact match? + int contextPathLength = contextPath.length(); + if (requestPath.length() == contextPathLength) { return true; } - // Does the request path prefix match? - if (requestPath.startsWith(contextPath)) { - - // Is it an exact match? - int contextPathLength = contextPath.length(); - if (requestPath.length() == contextPathLength) { - return true; - } - - // Is it a path-prefix match? - assert contextPathLength > 0; - return - // Case 1: The request path starts with the context - // path, but the context path has an extra path - // separator suffix. For instance, the context path is - // `/foo/` and the request path is `/foo/bar`. - contextPath.charAt(contextPathLength - 1) == '/' || - // Case 2: The request path starts with the - // context path, but the request path has an - // extra path separator suffix. For instance, - // context path is `/foo` and the request path - // is `/foo/` or `/foo/bar`. - requestPath.charAt(contextPathLength) == '/'; - - } - - return false; + // Is it a path-prefix match? + assert contextPathLength > 0; + return + // Case 1: The request path starts with the context + // path, but the context path has an extra path + // separator suffix. For instance, the context path is + // `/foo/` and the request path is `/foo/bar`. + contextPath.charAt(contextPathLength - 1) == '/' || + // Case 2: The request path starts with the + // context path, but the request path has an + // extra path separator suffix. For instance, + // context path is `/foo` and the request path + // is `/foo/` or `/foo/bar`. + requestPath.charAt(contextPathLength) == '/'; }); diff --git a/test/jdk/com/sun/net/httpserver/ContextPathMatcherPathPrefixTest.java b/test/jdk/com/sun/net/httpserver/ContextPathMatcherPathPrefixTest.java index e1cff62a45f..6b260636585 100644 --- a/test/jdk/com/sun/net/httpserver/ContextPathMatcherPathPrefixTest.java +++ b/test/jdk/com/sun/net/httpserver/ContextPathMatcherPathPrefixTest.java @@ -23,21 +23,30 @@ import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; + +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.URI; +import java.net.Socket; import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static java.net.http.HttpClient.Builder.NO_PROXY; import org.junit.jupiter.api.AfterAll; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; @@ -89,29 +98,88 @@ public class ContextPathMatcherPathPrefixTest { @Test void testContextPathAtRoot() throws Exception { + // Repeating all cases with both known (GET) and unknown (DOH) request methods to stress both paths try (var infra = new Infra("/")) { - infra.expect(200, "/foo", "/foo/", "/foo/bar", "/foobar"); + // 200 + infra.expect(200, "GET /foo"); + infra.expect(200, "GET /foo/"); + infra.expect(200, "GET /foo/bar"); + infra.expect(200, "GET /foobar"); + infra.expect(200, "DOH /foo"); + infra.expect(200, "DOH /foo/"); + infra.expect(200, "DOH /foo/bar"); + infra.expect(200, "DOH /foobar"); + // 404 + infra.expect(404, "GET foo"); + infra.expect(404, "GET *"); + infra.expect(404, "GET "); + infra.expect(404, "DOH foo"); + infra.expect(404, "DOH *"); + infra.expect(404, "DOH "); + // 400 + infra.expect(400, "GET"); + infra.expect(400, "DOH"); } } @Test void testContextPathAtSubDir() throws Exception { + // Repeating all cases with both known (GET) and unknown (DOH) request methods to stress both paths try (var infra = new Infra("/foo")) { - infra.expect(200, "/foo", "/foo/", "/foo/bar"); - infra.expect(404, "/foobar"); + // 200 + infra.expect(200, "GET /foo"); + infra.expect(200, "GET /foo/"); + infra.expect(200, "GET /foo/bar"); + infra.expect(200, "DOH /foo"); + infra.expect(200, "DOH /foo/"); + infra.expect(200, "DOH /foo/bar"); + // 404 + infra.expect(404, "GET /foobar"); // Differs from string prefix matching! + infra.expect(404, "GET foo"); + infra.expect(404, "GET *"); + infra.expect(404, "GET "); + infra.expect(404, "DOH /foobar"); // Differs from string prefix matching! + infra.expect(404, "DOH foo"); + infra.expect(404, "DOH *"); + infra.expect(404, "DOH "); + // 400 + infra.expect(400, "GET"); + infra.expect(400, "DOH"); } } @Test void testContextPathAtSubDirWithTrailingSlash() throws Exception { + // Repeating all cases with both known (GET) and unknown (DOH) request methods to stress both paths try (var infra = new Infra("/foo/")) { - infra.expect(200, "/foo/", "/foo/bar"); - infra.expect(404, "/foo", "/foobar"); + // 200 + infra.expect(200, "GET /foo/"); + infra.expect(200, "GET /foo/bar"); + infra.expect(200, "DOH /foo/"); + infra.expect(200, "DOH /foo/bar"); + // 404 + infra.expect(404, "GET /foo"); + infra.expect(404, "GET /foobar"); + infra.expect(404, "GET foo"); + infra.expect(404, "GET *"); + infra.expect(404, "GET "); + infra.expect(404, "DOH /foo"); + infra.expect(404, "DOH /foobar"); + infra.expect(404, "DOH foo"); + infra.expect(404, "DOH *"); + infra.expect(404, "DOH "); + // 400 + infra.expect(400, "GET"); + infra.expect(400, "DOH"); } } protected static final class Infra implements AutoCloseable { + /** Charset used for network and file I/O. */ + private static final Charset CHARSET = StandardCharsets.US_ASCII; + + /** Socket address the server will bind to. */ private static final InetSocketAddress LO_SA_0 = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); @@ -128,22 +196,51 @@ public class ContextPathMatcherPathPrefixTest { this.contextPath = contextPath; } - protected void expect(int statusCode, String... requestPaths) throws Exception { - for (String requestPath : requestPaths) { - var requestURI = URI.create("http://%s:%s%s".formatted( - server.getAddress().getHostString(), - server.getAddress().getPort(), - requestPath)); - var request = HttpRequest.newBuilder(requestURI).build(); - var response = CLIENT.send(request, HttpResponse.BodyHandlers.discarding()); - assertEquals( - statusCode, response.statusCode(), - "unexpected status code " + Map.of( - "contextPath", contextPath, - "requestPath", requestPath)); + protected void expect(int statusCode, String requestLinePrefix) { + try { + expect0(statusCode, requestLinePrefix); + } catch (Throwable exception) { + var extendedMessage = exception.getMessage() + " " + Map.of( + "contextPath", contextPath, + "requestLinePrefix", requestLinePrefix); + var extendedException = new RuntimeException(extendedMessage); + extendedException.setStackTrace(exception.getStackTrace()); + throw extendedException; } } + private void expect0(int statusCode, String requestLinePrefix) throws IOException { + + // Connect to the server + try (Socket socket = new Socket()) { + socket.connect(server.getAddress()); + + // Obtain the I/O streams + try (OutputStream outputStream = socket.getOutputStream(); + InputStream inputStream = socket.getInputStream(); + BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream, CHARSET))) { + + // Write the request + byte[] requestBytes = String + // `Connection: close` is required for `BufferedReader::readLine` to work. + .format("%s HTTP/1.1\r\nConnection: close\r\n\r\n", requestLinePrefix) + .getBytes(CHARSET); + outputStream.write(requestBytes); + outputStream.flush(); + + // Read the response status code + String statusLine = inputReader.readLine(); + assertNotNull(statusLine, "Unexpected EOF while reading status line"); + Matcher statusLineMatcher = Pattern.compile("^HTTP/1\\.1 (\\d+) .+$").matcher(statusLine); + assertTrue(statusLineMatcher.matches(), "Couldn't match status line: \"" + statusLine + "\""); + assertEquals(statusCode, Integer.parseInt(statusLineMatcher.group(1))); + + } + + } + + } + @Override public void close() { server.stop(0); diff --git a/test/jdk/com/sun/net/httpserver/ContextPathMatcherStringPrefixTest.java b/test/jdk/com/sun/net/httpserver/ContextPathMatcherStringPrefixTest.java index 3f3008a8531..4faa1463e1b 100644 --- a/test/jdk/com/sun/net/httpserver/ContextPathMatcherStringPrefixTest.java +++ b/test/jdk/com/sun/net/httpserver/ContextPathMatcherStringPrefixTest.java @@ -36,28 +36,32 @@ import org.junit.jupiter.api.Test; class ContextPathMatcherStringPrefixTest extends ContextPathMatcherPathPrefixTest { - @Test - @Override - void testContextPathAtRoot() throws Exception { - try (var infra = new Infra("/")) { - infra.expect(200, "/foo", "/foo/", "/foo/bar", "/foobar"); - } - } - @Test @Override void testContextPathAtSubDir() throws Exception { + // Repeating all cases with both known (GET) and unknown (DOH) request methods to stress both paths try (var infra = new Infra("/foo")) { - infra.expect(200, "/foo", "/foo/", "/foo/bar", "/foobar"); - } - } - - @Test - @Override - void testContextPathAtSubDirWithTrailingSlash() throws Exception { - try (var infra = new Infra("/foo/")) { - infra.expect(200, "/foo/", "/foo/bar"); - infra.expect(404, "/foo", "/foobar"); + // 200 + infra.expect(200, "GET /foo"); + infra.expect(200, "GET /foo/"); + infra.expect(200, "GET /foo/bar"); + infra.expect(200, "GET /foobar"); // Differs from path prefix matching! + infra.expect(200, "DOH /foo"); + infra.expect(200, "DOH /foo/"); + infra.expect(200, "DOH /foo/bar"); + infra.expect(200, "DOH /foobar"); // Differs from path prefix matching! + // 404 + infra.expect(404, "GET /"); + infra.expect(404, "GET foo"); + infra.expect(404, "GET *"); + infra.expect(404, "GET "); + infra.expect(404, "DOH /"); + infra.expect(404, "DOH foo"); + infra.expect(404, "DOH *"); + infra.expect(404, "DOH "); + // 400 + infra.expect(400, "GET"); + infra.expect(400, "DOH"); } } From 4d9d2c352b9daa8bdecea5303f49f2496c127115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Thu, 5 Mar 2026 14:15:08 +0000 Subject: [PATCH 075/170] 8284315: DocTrees.getElement is inconsistent with Elements.getTypeElement Reviewed-by: jlahoda, vromero --- .../classes/com/sun/source/util/DocTrees.java | 25 +-- .../com/sun/tools/javac/api/JavacTrees.java | 142 +++++++++--------- .../doclets/toolkit/util/CommentHelper.java | 7 +- .../jdk/javadoc/internal/doclint/Checker.java | 12 +- .../javadoc/doclet/testSeeTag/TestSeeTag.java | 10 +- .../tools/doclint/ReferenceTest.java | 2 +- .../langtools/tools/doclint/ReferenceTest.out | 14 +- .../tools/javac/doctree/ReferenceTest.java | 78 ++++++++-- 8 files changed, 184 insertions(+), 106 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java b/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java index 45a452bd0dd..44d9bd89917 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocTrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -195,23 +195,30 @@ public abstract class DocTrees extends Trees { /** * Returns the language model element referred to by the leaf node of the given - * {@link DocTreePath}, or {@code null} if unknown. + * {@link DocTreePath}, or {@code null} if the leaf node of {@code path} does + * not refer to an element. + * * @param path the path for the tree node - * @return the element + * @return the referenced element, or null + * @see #getType(DocTreePath) */ public abstract Element getElement(DocTreePath path); /** * Returns the language model type referred to by the leaf node of the given - * {@link DocTreePath}, or {@code null} if unknown. This method usually - * returns the same value as {@code getElement(path).asType()} for a - * {@code path} argument for which {@link #getElement(DocTreePath)} returns - * a non-null value, but may return a type that includes additional - * information, such as a parameterized generic type instead of a raw type. + * {@link DocTreePath}, or {@code null} if the leaf node of {@code path} does + * not refer to a type. + * + *

If {@link #getElement(DocTreePath)} returns a non-null value for a given {@code path} + * argument, this method usally returns the same value as {@code getElement(path).asType()}. + * However, there are cases where the returned type includes additional information, + * such as a parameterized generic type instead of a raw type. In other cases, such as with + * primitive or array types, the returned type may not have a corresponding element returned + * by {@code getElement(DocTreePath)}.

* * @param path the path for the tree node * @return the referenced type, or null - * + * @see #getElement(DocTreePath) * @since 15 */ public abstract TypeMirror getType(DocTreePath path); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java index 6bc5d358b6f..ecd7f5b101a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -354,22 +354,28 @@ public class JavacTrees extends DocTrees { DocTree tree = path.getLeaf(); if (tree instanceof DCReference dcReference) { JCTree qexpr = dcReference.qualifierExpression; - if (qexpr != null) { + + // Forward references with explicit module name to getElement + if (qexpr != null && dcReference.moduleName == null) { + + Env env = getAttrContext(path.getTreePath()); Log.DeferredDiagnosticHandler deferredDiagnosticHandler = log.new DeferredDiagnosticHandler(); + JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); + try { - Env env = getAttrContext(path.getTreePath()); - JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); - try { - Type t = attr.attribType(dcReference.qualifierExpression, env); - if (t != null && !t.isErroneous()) { + Type t = attr.attribType(dcReference.qualifierExpression, env); + if (t != null && !t.isErroneous()) { + if (dcReference.memberName != null) { + Symbol sym = resolveMember(t, (Name) dcReference.memberName, dcReference, env); + return sym == null ? null : sym.type; + } else { return t; } - } finally { - log.useSource(prevSource); } } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file return null; } finally { + log.useSource(prevSource); log.popDiagnosticHandler(deferredDiagnosticHandler); } } @@ -426,14 +432,12 @@ public class JavacTrees extends DocTrees { memberName = (Name) ref.memberName; } else { // Check if qualifierExpression is a type or package, using the methods javac provides. - // If no module name is given we check if qualifierExpression identifies a type. - // If that fails or we have a module name, use that to resolve qualifierExpression to - // a package or type. - Type t = ref.moduleName == null ? attr.attribType(ref.qualifierExpression, env) : null; + Type t = attr.attribType(ref.qualifierExpression, env); - if (t == null || t.isErroneous()) { - JCCompilationUnit toplevel = - treeMaker.TopLevel(List.nil()); + if (t == null || t.isErroneous() || + (ref.moduleName != null && !mdlsym.equals(elements.getModuleOf(t.asElement())))) { + + JCCompilationUnit toplevel = treeMaker.TopLevel(List.nil()); toplevel.modle = mdlsym; toplevel.packge = mdlsym.unnamedPackage; Symbol sym = attr.attribIdent(ref.qualifierExpression, toplevel); @@ -447,10 +451,6 @@ public class JavacTrees extends DocTrees { if ((sym.kind == PCK || sym.kind == TYP) && sym.exists()) { tsym = (TypeSymbol) sym; memberName = (Name) ref.memberName; - if (sym.kind == PCK && memberName != null) { - //cannot refer to a package "member" - return null; - } } else { if (modules.modulesInitialized() && ref.moduleName == null && ref.memberName == null) { // package/type does not exist, check if there is a matching module @@ -470,64 +470,22 @@ public class JavacTrees extends DocTrees { } } } else { - Type e = t; - // If this is an array type convert to element type - while (e instanceof ArrayType arrayType) - e = arrayType.elemtype; - tsym = e.tsym; + tsym = switch (t.getKind()) { + case DECLARED, TYPEVAR, PACKAGE, MODULE -> t.tsym; + default -> null; + }; memberName = (Name) ref.memberName; } } if (memberName == null) { return tsym; - } else if (tsym == null || tsym.getKind() == ElementKind.PACKAGE || tsym.getKind() == ElementKind.MODULE) { - return null; // Non-null member name in non-class context - } - - if (tsym.type.isPrimitive()) { + } else if (tsym == null) { return null; } - final List paramTypes; - if (ref.paramTypes == null) - paramTypes = null; - else { - ListBuffer lb = new ListBuffer<>(); - for (List l = (List) ref.paramTypes; l.nonEmpty(); l = l.tail) { - JCTree tree = l.head; - Type t = attr.attribType(tree, env); - lb.add(t); - } - paramTypes = lb.toList(); - } + return resolveMember(tsym.type, memberName, ref, env); - ClassSymbol sym = (ClassSymbol) types.skipTypeVars(tsym.type, false).tsym; - boolean explicitType = ref.qualifierExpression != null; - Symbol msym = (memberName == sym.name) - ? findConstructor(sym, paramTypes, true) - : findMethod(sym, memberName, paramTypes, true, explicitType); - - if (msym == null) { - msym = (memberName == sym.name) - ? findConstructor(sym, paramTypes, false) - : findMethod(sym, memberName, paramTypes, false, explicitType); - } - - if (paramTypes != null) { - // explicit (possibly empty) arg list given, so cannot be a field - return msym; - } - - VarSymbol vsym = (ref.paramTypes != null) ? null : findField(sym, memberName, explicitType); - // prefer a field over a method with no parameters - if (vsym != null && - (msym == null || - types.isSubtypeUnchecked(vsym.enclClass().asType(), msym.enclClass().asType()))) { - return vsym; - } else { - return msym; - } } catch (Abort e) { // may be thrown by Check.completionError in case of bad class file return null; } finally { @@ -536,6 +494,54 @@ public class JavacTrees extends DocTrees { } } + private Symbol resolveMember(Type type, Name memberName, DCReference ref, Env env) { + + if (type.isPrimitive() || type.getKind() == TypeKind.PACKAGE || type.getKind() == TypeKind.MODULE) { + return null; + } + + final List paramTypes; + if (ref.paramTypes == null) + paramTypes = null; + else { + ListBuffer lb = new ListBuffer<>(); + for (List l = (List) ref.paramTypes; l.nonEmpty(); l = l.tail) { + JCTree tree = l.head; + Type t = attr.attribType(tree, env); + lb.add(t); + } + paramTypes = lb.toList(); + } + + // skipTypeVars conversion below is needed if type is itself a type variable + ClassSymbol sym = (ClassSymbol) types.skipTypeVars(type, false).tsym; + boolean explicitType = ref.qualifierExpression != null; + Symbol msym = (memberName == sym.name) + ? findConstructor(sym, paramTypes, true) + : findMethod(sym, memberName, paramTypes, true, explicitType); + + if (msym == null) { + msym = (memberName == sym.name) + ? findConstructor(sym, paramTypes, false) + : findMethod(sym, memberName, paramTypes, false, explicitType); + } + + if (paramTypes != null) { + // explicit (possibly empty) arg list given, so cannot be a field + return msym; + } + + VarSymbol vsym = (ref.paramTypes != null) ? null : findField(sym, memberName, explicitType); + // prefer a field over a method with no parameters + if (vsym != null && + (msym == null || + types.isSubtypeUnchecked(vsym.enclClass().asType(), msym.enclClass().asType()))) { + return vsym; + } else { + return msym; + } + } + private Symbol attributeParamIdentifier(TreePath path, DCParam paramTag) { Symbol javadocSymbol = getElement(path); if (javadocSymbol == null) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java index 30aa86aea71..3d300b77073 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,10 +136,7 @@ public class CommentHelper { return null; } DocTrees doctrees = configuration.docEnv.getDocTrees(); - // Workaround for JDK-8284193 - // DocTrees.getElement(DocTreePath) returns javac-internal Symbols - var e = doctrees.getElement(docTreePath); - return e == null || e.getKind() == ElementKind.CLASS && e.asType().getKind() != TypeKind.DECLARED ? null : e; + return doctrees.getElement(docTreePath); } public TypeMirror getType(ReferenceTree rtree) { 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 b5399d0fef9..90b371a8a15 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1006,11 +1006,11 @@ public class Checker extends DocTreePathScanner { public Void visitReference(ReferenceTree tree, Void ignore) { // Exclude same-file anchor links from reference checks if (!tree.getSignature().startsWith("##")) { - Element e = env.trees.getElement(getCurrentPath()); - if (e == null) { - reportBadReference(tree); - } else if ((inLink || inSee) - && e.getKind() == ElementKind.CLASS && e.asType().getKind() != TypeKind.DECLARED) { + if (inLink || inSee) { + if (env.trees.getElement(getCurrentPath()) == null) { + reportBadReference(tree); + } + } else if (env.trees.getType(getCurrentPath()) == null) { reportBadReference(tree); } } diff --git a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java index f3294f6647c..57854396cf4 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 8017191 8182765 8200432 8239804 8250766 8262992 8281944 8307377 + * 8284315 * @summary Javadoc is confused by at-link to imported classes outside of the set of generated packages * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -103,7 +104,12 @@ public class TestSeeTag extends JavadocTester {
See Also:
    -
  • Object
  • +
  • +
    + invalid reference +
    Object[]
    +
    +
  • invalid reference diff --git a/test/langtools/tools/doclint/ReferenceTest.java b/test/langtools/tools/doclint/ReferenceTest.java index ca677d64927..63512d1efc4 100644 --- a/test/langtools/tools/doclint/ReferenceTest.java +++ b/test/langtools/tools/doclint/ReferenceTest.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8004832 8020556 8002154 8200432 8177280 + * @bug 8004832 8020556 8002154 8200432 8177280 8284315 * @summary Add new doclint package * @modules jdk.javadoc/jdk.javadoc.internal.doclint * @build DocLintTester diff --git a/test/langtools/tools/doclint/ReferenceTest.out b/test/langtools/tools/doclint/ReferenceTest.out index 0b39ea20a41..4232f7b12ba 100644 --- a/test/langtools/tools/doclint/ReferenceTest.out +++ b/test/langtools/tools/doclint/ReferenceTest.out @@ -31,12 +31,24 @@ ReferenceTest.java:71: error: reference not found ReferenceTest.java:74: error: reference not found * @see not.Found ^ +ReferenceTest.java:79: error: reference not found + * {@link java.lang.String[]} + ^ +ReferenceTest.java:80: error: reference not found + * {@link java.lang.String[]#equals} + ^ ReferenceTest.java:81: error: reference not found * {@link not.Found[]} ^ +ReferenceTest.java:82: error: reference not found + * @see java.lang.String[] + ^ +ReferenceTest.java:83: error: reference not found + * @see java.lang.String[]#equals + ^ ReferenceTest.java:84: error: reference not found * @see not.Found[] ^ -12 errors +16 errors 1 warning diff --git a/test/langtools/tools/javac/doctree/ReferenceTest.java b/test/langtools/tools/javac/doctree/ReferenceTest.java index 540cb9a6621..83a10ee4d20 100644 --- a/test/langtools/tools/javac/doctree/ReferenceTest.java +++ b/test/langtools/tools/javac/doctree/ReferenceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 7021614 8278373 8164094 8371248 + * @bug 7021614 8278373 8164094 8371248 8284315 * @summary extend com.sun.source API to support parsing javadoc comments * @summary check references in at-see and {at-link} tags * @modules jdk.compiler @@ -56,6 +56,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.QualifiedNameable; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic.Kind; @@ -84,11 +85,14 @@ import javax.tools.Diagnostic.Kind; * {@link #trees Field} * {@link #getSupportedSourceVersion Method} * {@link #init(ProcessingEnvironment Method} - * {@link double Class} + * {@link double type-only:double} + * {@link int type-only:int} + * {@link void type-only:void} * {@link double.NAN Bad} * {@link double#NAN Bad} * {@link double#double Bad} * {@link java.base/double Bad} + * {@link jdk.javadoc/double Bad} * * {@link List Interface} * {@link List.add Bad} @@ -100,15 +104,20 @@ import javax.tools.Diagnostic.Kind; * {@link Map.Entry#getKey Method} * {@link Map.Entry#setValue(Object) Method} * - * {@link java.base/java.util.List Bad} + * {@link java.lang.String[] type-only:array} + * {@link java.lang.String[].length Bad} + * {@link java.lang.String[]#length type-only:int} + * {@link java.lang.String[]#length() Bad} + * + * {@link java.base/java.util.List Interface} * {@link java.base/java.util.List.add Bad} - * {@link java.base/java.util.List#add Bad} - * {@link java.base/java.util.List#add(Object) Bad} - * {@link java.base/java.util.Map.Entry Bad} - * {@link java.base/java.util.Map.Entry Bad} + * {@link java.base/java.util.List#add Method} + * {@link java.base/java.util.List#add(Object) Method} + * {@link java.base/java.util.Map.Entry Interface} + * {@link java.base/java.util.Map.Entry Interface} * {@link java.base/java.util.Map.Entry.getKey Bad} - * {@link java.base/java.util.Map.Entry#getKey Bad} - * {@link java.base/java.util.Map.Entry#setValue(Object) Bad} + * {@link java.base/java.util.Map.Entry#getKey Method} + * {@link java.base/java.util.Map.Entry#setValue(Object) Method} * * @see java.lang Package * @see java.lang.ERROR Bad @@ -127,6 +136,14 @@ import javax.tools.Diagnostic.Kind; * @see java.lang.String#ERROR Bad * @see java.lang.String#equals(Object) Method * + * @see java.lang.String[] type-only:array + * @see java.lang.String[].length Bad + * @see java.lang.String[]#length type-only:int + * @see java.lang.String[]#length() Bad + * + * @see jdk.javadoc/jdk.javadoc.doclet.Doclet Interface + * @see jdk.compiler/jdk.javadoc.doclet.Doclet Bad + * * @see AbstractProcessor Class * * @see List#add(Object) Method @@ -200,15 +217,23 @@ public class ReferenceTest extends AbstractProcessor { String sig = tree.getSignature(); Element found = trees.getElement(new DocTreePath(getCurrentPath(), tree)); + TypeMirror type = trees.getType(new DocTreePath(getCurrentPath(), tree)); + if (found == null) { System.err.println(sig + " NOT FOUND"); } else { System.err.println(sig + " found " + found.getKind() + " " + found); + if (type == null) { + error(tree, "Did not find type for element " + found); + } else if (!erasure(type).equals(erasure(found.asType()))) { + error(tree, "Type " + erasure(type) + " does not match element " + erasure(found.asType())); + } } String expect = "UNKNOWN"; - if (label.size() > 0 && label.get(0) instanceof TextTree) - expect = ((TextTree) label.get(0)).getBody(); + if (!label.isEmpty() && label.getFirst() instanceof TextTree) { + expect = ((TextTree) label.getFirst()).getBody(); + } if (expect.startsWith("signature:")) { expect = expect.substring("signature:".length()); @@ -216,12 +241,25 @@ public class ReferenceTest extends AbstractProcessor { String signature = found.getKind().name() + ":" + elementSignature(found); if (!expect.equalsIgnoreCase(signature)) { - error(tree, "Unexpected value found: " + signature +", expected: " + expect); + error(tree, "Unexpected value found: " + signature + ", expected: " + expect); + } + } else if (expect.startsWith("type-only:")) { + expect = expect.substring("type-only:".length()); + if (found != null) { + error(tree, "Found element for type-only reference: " + found); + } + if (type == null) { + error(tree, "Found no type, expected: " + expect); + } else if (!expect.equalsIgnoreCase(type.getKind().name())) { + error(tree, "Found unexpected type: " + type + ", expected: " + expect); } } else { if (!expect.equalsIgnoreCase(found == null ? "bad" : found.getKind().name())) { error(tree, "Unexpected value found: " + found +", expected: " + expect); } + if (expect.equalsIgnoreCase("bad") && type != null) { + error(tree, "Found unexpected type: " + type + ", expected none"); + } } } @@ -252,6 +290,12 @@ public class ReferenceTest extends AbstractProcessor { default -> throw new AssertionError("Unhandled type kind: " + type.getKind()); }; } + + TypeMirror erasure(TypeMirror type) { + return type.getKind() == TypeKind.DECLARED + ? processingEnv.getTypeUtils().erasure(type) + : type; + } } /** @@ -317,11 +361,17 @@ class ReferenceTestExtras { * @see #X Field * @see #X() Method * @see #m Method + * @see X Type_Parameter + * @see Y Type_Parameter + * @see X#wait Method + * @see X#wait() Method + * @see Y#getSupportedSourceVersion Method + * @see Y#init(ProcessingEnvironment) Method * @see Inner#X Bad * @see Inner#X() Bad * @see Inner#m Bad */ - interface Inner {} + interface Inner {} } From 2cb177d0babe1684362df975ad69ea31dc499d5b Mon Sep 17 00:00:00 2001 From: Boris Ulasevich Date: Thu, 5 Mar 2026 16:10:44 +0000 Subject: [PATCH 076/170] 8371459: [REDO] AArch64: Use SHA3 GPR intrinsic where it's faster Reviewed-by: phh, bperez --- src/hotspot/cpu/aarch64/globals_aarch64.hpp | 2 +- .../cpu/aarch64/stubGenerator_aarch64.cpp | 15 +++++------- .../cpu/aarch64/vm_version_aarch64.cpp | 24 ++++++++++++++----- ...nsicsWithUseSHADisabledOnSupportedCPU.java | 4 ++-- ...icsWithUseSHADisabledOnUnsupportedCPU.java | 2 +- .../intrinsics/sha/cli/DigestOptionsBase.java | 2 +- ...UseSHA3IntrinsicsOptionOnSupportedCPU.java | 5 +--- .../GenericTestCaseForSupportedCPU.java | 3 ++- .../GenericTestCaseForUnsupportedCPU.java | 3 ++- .../sha/predicate/IntrinsicPredicates.java | 6 +++++ 10 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index a59e83c4b69..e6de2c798b1 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -95,7 +95,7 @@ define_pd_global(intx, InlineSmallCode, 1000); "Use simplest and shortest implementation for array equals") \ product(bool, UseSIMDForBigIntegerShiftIntrinsics, true, \ "Use SIMD instructions for left/right shift of BigInteger") \ - product(bool, UseSIMDForSHA3Intrinsic, true, \ + product(bool, UseSIMDForSHA3Intrinsic, false, \ "Use SIMD SHA3 instructions for SHA3 intrinsic") \ product(bool, AvoidUnalignedAccesses, false, \ "Avoid generating unaligned memory accesses") \ diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index a459a28b09e..21a1124a8ec 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -11876,16 +11876,13 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_sha512_implCompress = generate_sha512_implCompress(StubId::stubgen_sha512_implCompress_id); StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(StubId::stubgen_sha512_implCompressMB_id); } - if (UseSHA3Intrinsics) { - + if (UseSHA3Intrinsics && UseSIMDForSHA3Intrinsic) { StubRoutines::_double_keccak = generate_double_keccak(); - if (UseSIMDForSHA3Intrinsic) { - StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubId::stubgen_sha3_implCompress_id); - StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubId::stubgen_sha3_implCompressMB_id); - } else { - StubRoutines::_sha3_implCompress = generate_sha3_implCompress_gpr(StubId::stubgen_sha3_implCompress_id); - StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress_gpr(StubId::stubgen_sha3_implCompressMB_id); - } + StubRoutines::_sha3_implCompress = generate_sha3_implCompress(StubId::stubgen_sha3_implCompress_id); + StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(StubId::stubgen_sha3_implCompressMB_id); + } else if (UseSHA3Intrinsics) { + StubRoutines::_sha3_implCompress = generate_sha3_implCompress_gpr(StubId::stubgen_sha3_implCompress_id); + StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress_gpr(StubId::stubgen_sha3_implCompressMB_id); } if (UsePoly1305Intrinsics) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 9b85733ed08..4423d9c5b58 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -365,16 +365,28 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); } - if (UseSHA && VM_Version::supports_sha3()) { - // Auto-enable UseSHA3Intrinsics on hardware with performance benefit. - // Note that the evaluation of UseSHA3Intrinsics shows better performance + if (UseSHA) { + // No need to check VM_Version::supports_sha3(), since a fallback GPR intrinsic implementation is provided. + if (FLAG_IS_DEFAULT(UseSHA3Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA3Intrinsics, true); + } + } else if (UseSHA3Intrinsics) { + // Matches the documented and tested behavior: the -UseSHA option disables all SHA intrinsics. + warning("UseSHA3Intrinsics requires that UseSHA is enabled."); + FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); + } + + if (UseSHA3Intrinsics && VM_Version::supports_sha3()) { + // Auto-enable UseSIMDForSHA3Intrinsic on hardware with performance benefit. + // Note that the evaluation of SHA3 extension Intrinsics shows better performance // on Apple and Qualcomm silicon but worse performance on Neoverse V1 and N2. if (_cpu == CPU_APPLE || _cpu == CPU_QUALCOMM) { // Apple or Qualcomm silicon - if (FLAG_IS_DEFAULT(UseSHA3Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA3Intrinsics, true); + if (FLAG_IS_DEFAULT(UseSIMDForSHA3Intrinsic)) { + FLAG_SET_DEFAULT(UseSIMDForSHA3Intrinsic, true); } } - } else if (UseSHA3Intrinsics && UseSIMDForSHA3Intrinsic) { + } + if (UseSHA3Intrinsics && UseSIMDForSHA3Intrinsic && !VM_Version::supports_sha3()) { warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); } diff --git a/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnSupportedCPU.java b/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnSupportedCPU.java index cf8000b7a21..10be61e98ec 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnSupportedCPU.java +++ b/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnSupportedCPU.java @@ -52,7 +52,7 @@ public class TestUseSHA3IntrinsicsWithUseSHADisabledOnSupportedCPU { private static final String UNLOCK_DIAGNOSTIC = "-XX:+UnlockDiagnosticVMOptions"; public static void main(String[] args) throws Throwable { - if (!IntrinsicPredicates.SHA3_INSTRUCTION_AVAILABLE.getAsBoolean()) { + if (!IntrinsicPredicates.SHA3_INTRINSIC_AVAILABLE.getAsBoolean()) { throw new SkippedException("Skipping... SHA3 intrinsics are not available on this platform."); } @@ -111,7 +111,7 @@ public class TestUseSHA3IntrinsicsWithUseSHADisabledOnSupportedCPU { private static void testWarningWhenEnablingWithUseSHADisabled() throws Throwable { // A warning should be printed when trying to enable UseSHA3Intrinsics with -UseSHA CommandLineOptionTest.verifySameJVMStartup( - new String[] { WARNING_MESSAGE }, // Warning should appear + new String[] { "warning" }, // Warning should appear null, // No unexpected output "JVM should start successfully", String.format("A warning should be printed when trying to enable %s while %s is disabled", diff --git a/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnUnsupportedCPU.java index 1e0df1874b6..ebada79c877 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/arguments/TestUseSHA3IntrinsicsWithUseSHADisabledOnUnsupportedCPU.java @@ -51,7 +51,7 @@ public class TestUseSHA3IntrinsicsWithUseSHADisabledOnUnsupportedCPU { private static final String UNLOCK_DIAGNOSTIC = "-XX:+UnlockDiagnosticVMOptions"; public static void main(String[] args) throws Throwable { - if (IntrinsicPredicates.SHA3_INSTRUCTION_AVAILABLE.getAsBoolean()) { + if (IntrinsicPredicates.SHA3_INTRINSIC_AVAILABLE.getAsBoolean()) { throw new SkippedException("Skipping... SHA3 intrinsics are available on this platform."); } diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java index 22b3bba854c..b8a3896294b 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/DigestOptionsBase.java @@ -122,7 +122,7 @@ public class DigestOptionsBase extends CommandLineOptionTest { case DigestOptionsBase.USE_SHA512_INTRINSICS_OPTION: return IntrinsicPredicates.isSHA512IntrinsicAvailable(); case DigestOptionsBase.USE_SHA3_INTRINSICS_OPTION: - return IntrinsicPredicates.SHA3_INSTRUCTION_AVAILABLE; + return IntrinsicPredicates.SHA3_INTRINSIC_AVAILABLE; default: throw new Error("Unexpected option " + optionName); } diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java index d3c0a4a8da7..c47591d75da 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA3IntrinsicsOptionOnSupportedCPU.java @@ -28,10 +28,7 @@ * @summary Verify UseSHA3Intrinsics option processing on supported CPU. * @library /test/lib / * @requires vm.flagless - * @requires os.arch == "aarch64" & os.family == "mac" - * @comment sha3 is only implemented on AArch64 for now. - * UseSHA3Intrinsics is only auto-enabled on Apple silicon, because it - * may introduce performance regression on others. See JDK-8297092. + * @requires (os.arch == "aarch64" | os.arch == "amd64" | os.arch == "x86_64") * * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java index 4b3914e75fd..f1c7069c317 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java @@ -80,7 +80,8 @@ public class GenericTestCaseForSupportedCPU extends // Verify that if -XX:-UseSHA is passed to the JVM, it is not possible // to enable the tested option and a warning is printed. CommandLineOptionTest.verifySameJVMStartup( - new String[] { DigestOptionsBase.getWarningForUnsupportedCPU(optionName) }, + new String[] { "warning: " }, // Accept any warning message, e.g. "requires that UseSHA is enabled" + // or the common "not available on this CPU" message. null, shouldPassMessage, String.format("Enabling option '%s' should not be possible and should result in a warning if %s was passed to JVM", diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedCPU.java index 85f6f280ccb..b2a0720e6e8 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedCPU.java @@ -71,7 +71,8 @@ public class GenericTestCaseForUnsupportedCPU extends // a warning will occur in VM output if UseSHA is disabled. if (!optionName.equals(DigestOptionsBase.USE_SHA_OPTION)) { CommandLineOptionTest.verifySameJVMStartup( - new String[] { DigestOptionsBase.getWarningForUnsupportedCPU(optionName) }, + new String[] { "warning: " }, // Accept any warning message, e.g. "requires that UseSHA is enabled" + // or the common "not available on this CPU" message. null, shouldPassMessage, shouldPassMessage, diff --git a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java index 0c53c36af1d..b088f58bb5b 100644 --- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java +++ b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java @@ -109,6 +109,12 @@ public class IntrinsicPredicates { new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] {"avx512f", "avx512bw"}, null), new CPUSpecificPredicate("x86_64", new String[] {"avx512f", "avx512bw"}, null))); + public static final BooleanSupplier SHA3_INTRINSIC_AVAILABLE + // AArch64 has both SHA3-based and GPR-based implementations of the SHA3 intrinsic. No need for the SHA3 capability. + = new OrPredicate(new CPUSpecificPredicate("aarch64.*", null, null), + new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] {"avx512f", "avx512bw"}, null), + new CPUSpecificPredicate("x86_64", new String[] {"avx512f", "avx512bw"}, null))); + public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE = new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE, new OrPredicate(IntrinsicPredicates.SHA256_INSTRUCTION_AVAILABLE, From 9bd99b9d68d998dbb0158ed9d31e64b499159856 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Thu, 5 Mar 2026 16:42:07 +0000 Subject: [PATCH 077/170] 8378854: Disable SA tests when ZGC is being used Reviewed-by: ysuenaga, kevinw, syan, stefank --- test/hotspot/jtreg/ProblemList-zgc.txt | 76 ------------------- .../sa/TestHeapDumpForLargeArray.java | 6 +- .../serviceability/sa/CDSJMapClstats.java | 6 +- .../jtreg/serviceability/sa/ClhsdbAttach.java | 3 +- .../sa/ClhsdbAttachDifferentJVMs.java | 3 +- .../serviceability/sa/ClhsdbCDSCore.java | 3 +- .../sa/ClhsdbCDSJstackPrintAll.java | 6 +- .../serviceability/sa/ClhsdbClasses.java | 3 +- .../serviceability/sa/ClhsdbDumpclass.java | 3 +- .../serviceability/sa/ClhsdbDumpheap.java | 1 + .../jtreg/serviceability/sa/ClhsdbField.java | 3 +- .../jtreg/serviceability/sa/ClhsdbFindPC.java | 10 ++- .../jtreg/serviceability/sa/ClhsdbFlags.java | 3 +- .../serviceability/sa/ClhsdbHistory.java | 3 +- .../serviceability/sa/ClhsdbInspect.java | 1 + .../jtreg/serviceability/sa/ClhsdbJdis.java | 3 +- .../jtreg/serviceability/sa/ClhsdbJhisto.java | 3 +- .../jtreg/serviceability/sa/ClhsdbJstack.java | 4 +- .../sa/ClhsdbJstackWithConcurrentLock.java | 3 +- .../sa/ClhsdbJstackXcompStress.java | 3 +- .../serviceability/sa/ClhsdbLongConstant.java | 3 +- .../jtreg/serviceability/sa/ClhsdbPmap.java | 4 +- .../serviceability/sa/ClhsdbPrintAll.java | 3 +- .../serviceability/sa/ClhsdbPrintAs.java | 3 +- .../serviceability/sa/ClhsdbPrintStatics.java | 3 +- .../jtreg/serviceability/sa/ClhsdbPstack.java | 4 +- .../serviceability/sa/ClhsdbScanOops.java | 6 +- .../jtreg/serviceability/sa/ClhsdbSource.java | 3 +- .../jtreg/serviceability/sa/ClhsdbSymbol.java | 3 +- .../sa/ClhsdbTestAllocationMerge.java | 3 +- .../jtreg/serviceability/sa/ClhsdbThread.java | 3 +- .../sa/ClhsdbThreadContext.java | 3 +- .../sa/ClhsdbVmStructsDump.java | 3 +- .../jtreg/serviceability/sa/ClhsdbWhere.java | 3 +- .../sa/DeadlockDetectionTest.java | 3 +- .../sa/JhsdbThreadInfoTest.java | 3 +- .../serviceability/sa/TestClassDump.java | 3 +- .../sa/TestClhsdbJstackLock.java | 3 +- .../sa/TestCpoolForInvokeDynamic.java | 3 +- .../sa/TestDebugInfoDecode.java | 3 +- .../serviceability/sa/TestDefaultMethods.java | 3 +- .../sa/TestHeapDumpForInvokeDynamic.java | 3 +- .../sa/TestInstanceKlassSize.java | 3 +- .../sa/TestInstanceKlassSizeForInterface.java | 3 +- .../serviceability/sa/TestIntConstant.java | 3 +- .../sa/TestJhsdbJstackLineNumbers.java | 3 +- .../sa/TestJhsdbJstackLock.java | 3 +- .../sa/TestJhsdbJstackMixed.java | 4 +- .../sa/TestJhsdbJstackMixedCore.java | 4 +- .../TestJhsdbJstackMixedWithVDSOCallCore.java | 4 +- .../sa/TestJhsdbJstackMixedWithXComp.java | 5 +- .../sa/TestJhsdbJstackPrintVMLocks.java | 3 +- .../sa/TestJhsdbJstackUpcall.java | 3 +- .../sa/TestJhsdbJstackWithVirtualThread.java | 3 +- .../jtreg/serviceability/sa/TestJmapCore.java | 3 +- .../sa/TestJmapCoreMetaspace.java | 3 +- .../sa/TestObjectAlignment.java | 6 +- .../sa/TestObjectMonitorIterate.java | 3 +- .../sa/TestRevPtrsForInvokeDynamic.java | 3 +- .../jtreg/serviceability/sa/TestSysProps.java | 3 +- .../jtreg/serviceability/sa/TestType.java | 3 +- .../serviceability/sa/UniqueVtableTest.java | 3 +- .../sa/jmap-hprof/JMapHProfLargeHeapTest.java | 3 +- .../sadebugd/ClhsdbAttachToDebugServer.java | 3 +- .../sadebugd/ClhsdbTestConnectArgument.java | 3 +- .../sa/sadebugd/DebugdConnectTest.java | 3 +- .../sa/sadebugd/DisableRegistryTest.java | 3 +- .../sa/sadebugd/PmapOnDebugdTest.java | 3 +- .../sa/sadebugd/RunCommandOnServerTest.java | 3 +- .../sa/sadebugd/SADebugDTest.java | 3 +- test/jdk/ProblemList-zgc.txt | 10 --- .../sun/tools/jhsdb/BasicLauncherTest.java | 3 +- test/jdk/sun/tools/jhsdb/HeapDumpTest.java | 3 +- .../jhsdb/HeapDumpTestWithActiveProcess.java | 3 +- .../sun/tools/jhsdb/JShellHeapDumpTest.java | 3 +- .../jdk/sun/tools/jhsdb/JStackStressTest.java | 3 +- .../jhsdb/heapconfig/JMapHeapConfigTest.java | 3 +- 77 files changed, 170 insertions(+), 167 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 3e52b7169df..8514ffce11c 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -27,82 +27,6 @@ # ############################################################################# -# Quiet the majority of SA tests -# We run serviceability/sa/TestUniverse.java as a sanity check for minimal functionality - -resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java 8307393 generic-all -serviceability/sa/CDSJMapClstats.java 8307393 generic-all -serviceability/sa/ClhsdbAttach.java 8307393 generic-all -serviceability/sa/ClhsdbAttachDifferentJVMs.java 8307393 generic-all -serviceability/sa/ClhsdbCDSCore.java 8307393 generic-all -serviceability/sa/ClhsdbCDSJstackPrintAll.java 8307393 generic-all -serviceability/sa/ClhsdbClasses.java 8307393 generic-all -serviceability/sa/ClhsdbDumpclass.java 8307393 generic-all -serviceability/sa/ClhsdbDumpheap.java 8307393 generic-all -serviceability/sa/ClhsdbField.java 8307393 generic-all -serviceability/sa/ClhsdbFindPC.java#no-xcomp-core 8307393 generic-all -serviceability/sa/ClhsdbFindPC.java#no-xcomp-process 8307393 generic-all -serviceability/sa/ClhsdbFindPC.java#xcomp-core 8307393 generic-all -serviceability/sa/ClhsdbFindPC.java#xcomp-process 8307393 generic-all -serviceability/sa/ClhsdbFlags.java 8307393 generic-all -serviceability/sa/ClhsdbHistory.java 8307393 generic-all -serviceability/sa/ClhsdbInspect.java 8307393 generic-all -serviceability/sa/ClhsdbJdis.java 8307393 generic-all -serviceability/sa/ClhsdbJhisto.java 8307393 generic-all -serviceability/sa/ClhsdbJstack.java#id0 8307393 generic-all -serviceability/sa/ClhsdbJstack.java#id1 8307393 generic-all -serviceability/sa/ClhsdbJstackWithConcurrentLock.java 8307393 generic-all -serviceability/sa/ClhsdbJstackXcompStress.java 8307393 generic-all -serviceability/sa/ClhsdbLongConstant.java 8307393 generic-all -serviceability/sa/ClhsdbPmap.java#core 8307393 generic-all -serviceability/sa/ClhsdbPmap.java#process 8307393 generic-all -serviceability/sa/ClhsdbPrintAll.java 8307393 generic-all -serviceability/sa/ClhsdbPrintAs.java 8307393 generic-all -serviceability/sa/ClhsdbPrintStatics.java 8307393 generic-all -serviceability/sa/ClhsdbPstack.java#core 8307393 generic-all -serviceability/sa/ClhsdbPstack.java#process 8307393 generic-all -serviceability/sa/ClhsdbScanOops.java#parallel 8307393 generic-all -serviceability/sa/ClhsdbScanOops.java#serial 8307393 generic-all -serviceability/sa/ClhsdbSource.java 8307393 generic-all -serviceability/sa/ClhsdbSymbol.java 8307393 generic-all -serviceability/sa/ClhsdbThread.java 8307393 generic-all -serviceability/sa/ClhsdbThreadContext.java 8307393 generic-all -serviceability/sa/ClhsdbVmStructsDump.java 8307393 generic-all -serviceability/sa/ClhsdbWhere.java 8307393 generic-all -serviceability/sa/DeadlockDetectionTest.java 8307393 generic-all -serviceability/sa/JhsdbThreadInfoTest.java 8307393 generic-all -serviceability/sa/TestClassDump.java 8307393 generic-all -serviceability/sa/TestClhsdbJstackLock.java 8307393 generic-all -serviceability/sa/TestCpoolForInvokeDynamic.java 8307393 generic-all -serviceability/sa/TestDefaultMethods.java 8307393 generic-all -serviceability/sa/TestG1HeapRegion.java 8307393 generic-all -serviceability/sa/TestHeapDumpForInvokeDynamic.java 8307393 generic-all -serviceability/sa/TestInstanceKlassSize.java 8307393 generic-all -serviceability/sa/TestInstanceKlassSizeForInterface.java 8307393 generic-all -serviceability/sa/TestIntConstant.java 8307393 generic-all -serviceability/sa/TestJhsdbJstackLineNumbers.java 8307393 generic-all -serviceability/sa/TestJhsdbJstackLock.java 8307393 generic-all -serviceability/sa/TestJhsdbJstackMixed.java 8307393 generic-all -serviceability/sa/TestJhsdbJstackPrintVMLocks.java 8307393 generic-all -serviceability/sa/TestJhsdbJstackUpcall.java 8307393 generic-all -serviceability/sa/TestJmapCore.java 8307393 generic-all -serviceability/sa/TestJmapCoreMetaspace.java 8307393 generic-all -serviceability/sa/TestObjectAlignment.java 8307393 generic-all -serviceability/sa/TestObjectMonitorIterate.java 8307393 generic-all -serviceability/sa/TestPrintMdo.java 8307393 generic-all -serviceability/sa/TestRevPtrsForInvokeDynamic.java 8307393 generic-all -serviceability/sa/TestSysProps.java 8307393 generic-all -serviceability/sa/TestType.java 8307393 generic-all -serviceability/sa/UniqueVtableTest.java 8307393 generic-all -serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java 8307393 generic-all -serviceability/sa/sadebugd/ClhsdbAttachToDebugServer.java 8307393 generic-all -serviceability/sa/sadebugd/ClhsdbTestConnectArgument.java 8307393 generic-all -serviceability/sa/ClhsdbTestAllocationMerge.java 8307393 generic-all -serviceability/sa/sadebugd/DebugdConnectTest.java 8307393 generic-all -serviceability/sa/sadebugd/DisableRegistryTest.java 8307393 generic-all -serviceability/sa/sadebugd/PmapOnDebugdTest.java 8307393 generic-all -serviceability/sa/sadebugd/RunCommandOnServerTest.java 8307393 generic-all -serviceability/sa/sadebugd/SADebugDTest.java 8307393 generic-all vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows-x64 diff --git a/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java b/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java index 553b8fbac35..cf32880c182 100644 --- a/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java +++ b/test/hotspot/jtreg/resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,9 @@ import jdk.test.lib.Utils; * @test * @library /test/lib * @bug 8171084 - * @requires vm.hasSA & (vm.bits == "64" & os.maxMemory > 8g) + * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires vm.bits == "64" & os.maxMemory > 8g * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.utilities diff --git a/test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java b/test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java index 4fd202a18da..8a9f148b3be 100644 --- a/test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java +++ b/test/hotspot/jtreg/serviceability/sa/CDSJMapClstats.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,9 @@ * @test * @bug 8204308 * @summary Test the jhsdb jmap -clstats command with CDS enabled - * @requires vm.hasSA & vm.cds + * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires vm.cds * @library /test/lib * @run driver/timeout=2400 CDSJMapClstats */ diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java index 57cd535a430..6493a803e90 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @bug 8191658 * @summary Test clhsdb attach, detach, reattach commands * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbAttach diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttachDifferentJVMs.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttachDifferentJVMs.java index 09f90355e67..f6833d5379a 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbAttachDifferentJVMs.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttachDifferentJVMs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @bug 8314679 * @summary Test clhsdb attach, detach, and then attach to different JVM * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbAttachDifferentJVMs diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java index aa3b19c4fcf..ab5b73bf720 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java @@ -25,8 +25,9 @@ * @test * @bug 8174994 8200613 * @summary Test the clhsdb commands 'printall', 'jstack' on a CDS enabled corefile. - * @requires vm.cds * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires vm.cds * @requires vm.flavor == "server" * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java index 4d01f9a26c8..c1e632782e2 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,9 @@ * @test * @bug 8174994 * @summary Test the clhsdb commands 'jstack', 'printall', 'where' with CDS enabled - * @requires vm.hasSA & vm.cds + * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires vm.cds * @library /test/lib * @run main/othervm/timeout=2400 -Xmx1g ClhsdbCDSJstackPrintAll */ diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbClasses.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbClasses.java index 3193f03bbc7..c4d11d29ec1 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbClasses.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @bug 8242142 * @summary Test clhsdb class and classes commands * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbClasses diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpclass.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpclass.java index e45318e201d..49a3eb5615c 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpclass.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpclass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import jtreg.SkippedException; * @bug 8240990 * @summary Test clhsdb dumpclass command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver ClhsdbDumpclass diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpheap.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpheap.java index d9f856ab0a3..92ec1c5d160 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpheap.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbDumpheap.java @@ -43,6 +43,7 @@ import jtreg.SkippedException; * @bug 8240989 * @summary Test clhsdb dumpheap command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires vm.compMode != "Xcomp" * @comment Running this test with -Xcomp is slow and therefore tends to cause diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java index 7dc676f1f3a..1df35dccce3 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import jtreg.SkippedException; * @bug 8191538 * @summary Test clhsdb 'field' command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbField diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java index 7ced4c9515b..1997e497af8 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,9 @@ import jtreg.SkippedException; * @test id=xcomp-process * @bug 8193124 * @summary Test the clhsdb 'findpc' command with Xcomp on live process - * @requires vm.compMode != "Xcomp" * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires vm.compMode != "Xcomp" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires vm.compiler1.enabled * @requires vm.opt.DeoptimizeALot != true @@ -48,8 +49,9 @@ import jtreg.SkippedException; * @test id=xcomp-core * @bug 8193124 * @summary Test the clhsdb 'findpc' command with Xcomp on core file - * @requires vm.compMode != "Xcomp" * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires vm.compMode != "Xcomp" * @requires vm.compiler1.enabled * @requires vm.opt.DeoptimizeALot != true * @library /test/lib @@ -61,6 +63,7 @@ import jtreg.SkippedException; * @bug 8193124 * @summary Test the clhsdb 'findpc' command w/o Xcomp on live process * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires vm.compiler1.enabled * @library /test/lib @@ -72,6 +75,7 @@ import jtreg.SkippedException; * @bug 8193124 * @summary Test the clhsdb 'findpc' command w/o Xcomp on core file * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires vm.compiler1.enabled * @library /test/lib * @run main/othervm/timeout=1920 ClhsdbFindPC false true diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java index a19f3e1ca16..1c8cf7191dd 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import jtreg.SkippedException; * @bug 8217845 * @summary Test clhsdb flags command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver ClhsdbFlags diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbHistory.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbHistory.java index e8416cbadd8..5dabb898936 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbHistory.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbHistory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import jtreg.SkippedException; * @bug 8217845 * @summary Test clhsdb command line history support * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbHistory diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java index 553706e502d..c0c062223d4 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java @@ -26,6 +26,7 @@ * @bug 8192985 * @summary Test the clhsdb 'inspect' command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm/timeout=480 ClhsdbInspect diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJdis.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJdis.java index 756e45f68aa..6c0ff0e3dbe 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJdis.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJdis.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8193124 * @summary Test the clhsdb 'jdis' command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbJdis diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java index ef30a97a026..a582b01e832 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import jtreg.SkippedException; * @bug 8191658 * @summary Test clhsdb jhisto command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbJhisto diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstack.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstack.java index 411664f195d..f066950cfc3 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstack.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @bug 8190198 * @summary Test clhsdb Jstack command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm/timeout=480 ClhsdbJstack true @@ -44,6 +45,7 @@ import jtreg.SkippedException; * @requires vm.compMode != "Xcomp" * @summary Test clhsdb Jstack command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm/timeout=480 ClhsdbJstack false diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java index 64080b252c5..e3d586c9d8a 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8324066 * @summary Test the clhsdb 'jstack -l' command for printing concurrent lock information * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbJstackWithConcurrentLock diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java index 4b02c01119d..a24b401dc47 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,6 +36,7 @@ import jdk.test.lib.process.OutputAnalyzer; * @test * @bug 8196969 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires vm.opt.DeoptimizeALot != true * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java index fceb2097e46..7fd3eb23d02 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8190198 * @summary Test clhsdb longConstant command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbLongConstant diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java index 5c0aa9457ae..885694f7abb 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import jtreg.SkippedException; * @bug 8190198 * @summary Test clhsdb pmap command on a live process * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbPmap false @@ -45,6 +46,7 @@ import jtreg.SkippedException; * @bug 8190198 * @summary Test clhsdb pmap command on a core file * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @run main/othervm/timeout=480 ClhsdbPmap true */ diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java index ac5ddf774e1..a62142c2c5c 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAll.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import jtreg.SkippedException; * @bug 8175384 * @summary Test clhsdb 'printall' command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm/timeout=2400 -Xmx2g ClhsdbPrintAll diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAs.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAs.java index 03ce8cd3048..c7e7e979b6d 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAs.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintAs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8192985 * @summary Test the clhsdb 'printas' command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbPrintAs diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java index c6f83c06845..e68e3ca4c47 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @bug 8190198 * @summary Test clhsdb printstatics command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbPrintStatics diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java index 15d88400917..51738be3554 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import jtreg.SkippedException; * @bug 8190198 * @summary Test clhsdb pstack command on a live process * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbPstack false @@ -45,6 +46,7 @@ import jtreg.SkippedException; * @bug 8190198 * @summary Test clhsdb pstack command on a core file * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @run main/othervm/timeout=480 ClhsdbPstack true */ diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java index 3b2aefec664..89c033f333a 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ * @test id=parallel * @bug 8192985 * @summary Test the clhsdb 'scanoops' command - * @requires vm.gc.Parallel * @requires vm.hasSA + * @requires vm.gc.Parallel * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm/timeout=1200 ClhsdbScanOops UseParallelGC @@ -36,8 +36,8 @@ * @test id=serial * @bug 8192985 * @summary Test the clhsdb 'scanoops' command - * @requires vm.gc.Serial * @requires vm.hasSA + * @requires vm.gc.Serial * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm/timeout=1200 ClhsdbScanOops UseSerialGC diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbSource.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbSource.java index c66e44aa213..8ec946e3ea1 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbSource.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbSource.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import jtreg.SkippedException; * @bug 8192823 * @summary Test clhsdb source command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbSource diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java index fe26427d6ce..ca05ba1d33e 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbSymbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.util.Map; * @bug 8261095 * @summary Test the clhsdb 'symbol' command on live process * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbSymbol diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java index d076e648d90..05054f31c51 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbTestAllocationMerge.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import jtreg.SkippedException; * @bug 8318682 * @summary Test clhsdb that decoding of AllocationMerge objects in debug info works correctly * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbTestAllocationMerge diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbThread.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbThread.java index f72b51585f5..e9a0b611134 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbThread.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @bug 8193352 * @summary Test clhsdb 'thread' and 'threads' commands * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbThread diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java index 5c3092a139d..c452575b782 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbThreadContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @test * @summary Test clhsdb where command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm/timeout=480 ClhsdbThreadContext diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java index 21db0e867a4..b00138e0c39 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import jtreg.SkippedException; * @bug 8191538 * @summary Test clhsdb 'vmstructsdump' command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbVmStructsDump diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java index 4536d568212..971f30fd94f 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbWhere.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @bug 8190198 * @summary Test clhsdb where command * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm ClhsdbWhere diff --git a/test/hotspot/jtreg/serviceability/sa/DeadlockDetectionTest.java b/test/hotspot/jtreg/serviceability/sa/DeadlockDetectionTest.java index cf9c4dfc5a1..ada0003fba5 100644 --- a/test/hotspot/jtreg/serviceability/sa/DeadlockDetectionTest.java +++ b/test/hotspot/jtreg/serviceability/sa/DeadlockDetectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @summary Test deadlock detection * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java index 75942f7113a..a13106b1401 100644 --- a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java +++ b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import jdk.test.lib.Utils; /** * @test * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver JhsdbThreadInfoTest diff --git a/test/hotspot/jtreg/serviceability/sa/TestClassDump.java b/test/hotspot/jtreg/serviceability/sa/TestClassDump.java index c163d45e0ba..c415332291e 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestClassDump.java +++ b/test/hotspot/jtreg/serviceability/sa/TestClassDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jtreg.SkippedException; * @bug 8184982 * @summary Test ClassDump tool * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver TestClassDump diff --git a/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java b/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java index a0a1051beca..8524b4cd489 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java +++ b/test/hotspot/jtreg/serviceability/sa/TestClhsdbJstackLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import jtreg.SkippedException; * @test * @bug 8185796 8335743 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm TestClhsdbJstackLock diff --git a/test/hotspot/jtreg/serviceability/sa/TestCpoolForInvokeDynamic.java b/test/hotspot/jtreg/serviceability/sa/TestCpoolForInvokeDynamic.java index b1f2148954c..2d6c208164a 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestCpoolForInvokeDynamic.java +++ b/test/hotspot/jtreg/serviceability/sa/TestCpoolForInvokeDynamic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import jdk.test.lib.Utils; * @test * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot diff --git a/test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java b/test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java index eb59f6f9487..3d808da683d 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java +++ b/test/hotspot/jtreg/serviceability/sa/TestDebugInfoDecode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import jdk.test.lib.SA.SATestUtils; * @bug 8318682 * @summary Test decoding debug info for all nmethods in the code cache * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @modules jdk.hotspot.agent/sun.jvm.hotspot diff --git a/test/hotspot/jtreg/serviceability/sa/TestDefaultMethods.java b/test/hotspot/jtreg/serviceability/sa/TestDefaultMethods.java index 3bbb6fcdf35..c8efec888ca 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestDefaultMethods.java +++ b/test/hotspot/jtreg/serviceability/sa/TestDefaultMethods.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ import jdk.test.lib.Utils; * @test * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot diff --git a/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java b/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java index 418dc5ec5a0..8ed476a0a1f 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java +++ b/test/hotspot/jtreg/serviceability/sa/TestHeapDumpForInvokeDynamic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jdk.test.lib.hprof.HprofParser; * @test * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot diff --git a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java index 3dbfbecda73..d1ed4729d39 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java +++ b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import java.util.*; * @test * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot diff --git a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java index a462ee30fb2..fd192212bc4 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java +++ b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ import jdk.test.lib.Utils; * @test * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot diff --git a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java index 2b41394b7a5..23e64452652 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java +++ b/test/hotspot/jtreg/serviceability/sa/TestIntConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import jtreg.SkippedException; * @summary Test the 'intConstant' command of jhsdb clhsdb. * @bug 8190307 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm TestIntConstant diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java index 15b9aa9ccae..936532527d4 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLineNumbers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jdk.test.lib.SA.SATestUtils; * @test * @bug 8214226 8243500 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires os.arch=="amd64" | os.arch=="x86_64" * @requires os.family=="windows" | os.family == "linux" | os.family == "mac" * @requires vm.flagless diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java index ac536523815..c9c85b3d25f 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import jdk.test.lib.Utils; * @test * @bug 8185796 8335743 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver TestJhsdbJstackLock diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java index e90418b1030..e3808aa6706 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixed.java @@ -37,7 +37,9 @@ import jdk.test.lib.process.OutputAnalyzer; * @test * @key randomness * @bug 8208091 8374469 8377710 - * @requires (os.family == "linux" | os.family == "windows") & (vm.hasSA) + * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires (os.family == "linux" | os.family == "windows") * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver TestJhsdbJstackMixed diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedCore.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedCore.java index 84a62eb65e5..99232ed9813 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedCore.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedCore.java @@ -38,7 +38,9 @@ import jtreg.SkippedException; /** * @test * @bug 8374482 8376264 8376284 8377395 - * @requires (os.family == "linux") & (vm.hasSA) + * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires os.family == "linux" * @requires os.arch == "amd64" * @library /test/lib * @run driver TestJhsdbJstackMixedCore diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithVDSOCallCore.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithVDSOCallCore.java index 84da46e272f..de512b93121 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithVDSOCallCore.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithVDSOCallCore.java @@ -38,7 +38,9 @@ import jdk.test.lib.util.CoreUtils; /** * @test * @bug 8376269 - * @requires (os.family == "linux") & (vm.hasSA) + * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires os.family == "linux" * @requires os.arch == "amd64" * @library /test/lib * @run driver TestJhsdbJstackMixedWithVDSOCallCore diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithXComp.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithXComp.java index a26fc4532df..1ebf6c21a70 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithXComp.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackMixedWithXComp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, NTT DATA * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,6 +36,7 @@ import jdk.test.lib.process.OutputAnalyzer; * @test id=xcomp * @bug 8370176 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires os.family == "linux" * @requires os.arch == "amd64" * @library /test/lib @@ -46,6 +47,7 @@ import jdk.test.lib.process.OutputAnalyzer; * @test id=xcomp-preserve-frame-pointer * @bug 8370176 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires os.family == "linux" * @requires os.arch == "amd64" * @library /test/lib @@ -56,6 +58,7 @@ import jdk.test.lib.process.OutputAnalyzer; * @test id=xcomp-disable-tiered-compilation * @bug 8370176 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires os.family == "linux" * @requires os.arch == "amd64" * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java index b7b3c956441..f6580d71e05 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import jtreg.SkippedException; * @test * @summary Test verifies that jstack --mixed prints information about VM locks * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @build jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackUpcall.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackUpcall.java index 1873672d2ce..e91910c3411 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackUpcall.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackUpcall.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import jdk.test.lib.process.OutputAnalyzer; * @test * @bug 8339307 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver TestJhsdbJstackUpcall diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java index 39b6e1ed609..55751c330b5 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, NTT DATA * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -37,6 +37,7 @@ import jdk.test.lib.process.OutputAnalyzer; * @test * @bug 8369505 * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @run driver TestJhsdbJstackWithVirtualThread */ diff --git a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java index 77258bd45b7..024b5e03c98 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test TestJmapCore * @summary Test verifies that jhsdb jmap could generate heap dump from core when heap is full * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires !vm.asan * @library /test/lib * @run driver/timeout=480 TestJmapCore run heap diff --git a/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java b/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java index ec3c66476a6..372cd0246ac 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJmapCoreMetaspace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test TestJmapCoreMetaspace * @summary Test verifies that jhsdb jmap could generate heap dump from core when metaspace is full * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires !vm.asan * @library /test/lib * @run driver/timeout=480 TestJmapCore run metaspace diff --git a/test/hotspot/jtreg/serviceability/sa/TestObjectAlignment.java b/test/hotspot/jtreg/serviceability/sa/TestObjectAlignment.java index 62fe2f5d7aa..081dbe1206c 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestObjectAlignment.java +++ b/test/hotspot/jtreg/serviceability/sa/TestObjectAlignment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,9 @@ import jdk.test.lib.Utils; /** * @test * @library /test/lib - * @requires vm.hasSA & vm.bits == "64" + * @requires vm.hasSA + * @requires vm.gc != "Z" + * @requires vm.bits == "64" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.runtime diff --git a/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java b/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java index 86a00285ee4..0448cc0788a 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java +++ b/test/hotspot/jtreg/serviceability/sa/TestObjectMonitorIterate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,6 +38,7 @@ import jdk.test.lib.SA.SATestUtils; * @bug 8259008 * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.oops diff --git a/test/hotspot/jtreg/serviceability/sa/TestRevPtrsForInvokeDynamic.java b/test/hotspot/jtreg/serviceability/sa/TestRevPtrsForInvokeDynamic.java index 315c931d49e..8c5ce3ae3cd 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestRevPtrsForInvokeDynamic.java +++ b/test/hotspot/jtreg/serviceability/sa/TestRevPtrsForInvokeDynamic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import jdk.test.lib.Utils; * @test * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @modules java.base/jdk.internal.misc * jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.utilities diff --git a/test/hotspot/jtreg/serviceability/sa/TestSysProps.java b/test/hotspot/jtreg/serviceability/sa/TestSysProps.java index a591d009ecf..a2617f7f268 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestSysProps.java +++ b/test/hotspot/jtreg/serviceability/sa/TestSysProps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jdk.test.lib.SA.SATestUtils; * @bug 8242165 8242162 * @summary Test "jhsdb jinfo --sysprops", "jinfo -sysprops", and clhsdb "sysprops" commands * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run driver TestSysProps diff --git a/test/hotspot/jtreg/serviceability/sa/TestType.java b/test/hotspot/jtreg/serviceability/sa/TestType.java index c3326032b90..e5b90a3c2a9 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestType.java +++ b/test/hotspot/jtreg/serviceability/sa/TestType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import jtreg.SkippedException; * @summary Test the 'type' command of jhsdb clhsdb. * @bug 8190307 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @library /test/lib * @run main/othervm TestType diff --git a/test/hotspot/jtreg/serviceability/sa/UniqueVtableTest.java b/test/hotspot/jtreg/serviceability/sa/UniqueVtableTest.java index 774fcee50ed..7792ec1a003 100644 --- a/test/hotspot/jtreg/serviceability/sa/UniqueVtableTest.java +++ b/test/hotspot/jtreg/serviceability/sa/UniqueVtableTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @modules jdk.hotspot.agent/sun.jvm.hotspot * jdk.hotspot.agent/sun.jvm.hotspot.debugger diff --git a/test/hotspot/jtreg/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java b/test/hotspot/jtreg/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java index a41ab71f4fa..6a7c519fedf 100644 --- a/test/hotspot/jtreg/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java +++ b/test/hotspot/jtreg/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ import jdk.test.lib.SA.SATestUtils; * @test * @bug 6313383 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @summary Regression test for hprof export issue due to large heaps (>2G) * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbAttachToDebugServer.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbAttachToDebugServer.java index 57962e72c5c..ab211b70691 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbAttachToDebugServer.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbAttachToDebugServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,6 +36,7 @@ import jtreg.SkippedException; * @bug 8262520 * @summary Test clhsdb connect, detach, reattach commands * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires os.family != "windows" * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbTestConnectArgument.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbTestConnectArgument.java index 109afa21841..2e07dfa63f0 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbTestConnectArgument.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbTestConnectArgument.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -35,6 +35,7 @@ import jtreg.SkippedException; * @test * @bug 8263342 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires os.family != "windows" * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java index 285f57f8115..7576aa54bf0 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8209790 * @summary Checks ability for connecting to debug server (jstack, jmap, jinfo, jsnap) * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires os.family != "windows" * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/DisableRegistryTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/DisableRegistryTest.java index ae0774988a8..312e99c172c 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/DisableRegistryTest.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/DisableRegistryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,6 +36,7 @@ import jtreg.SkippedException; * @bug 8263636 8263635 * @summary Test to use already started RMI registry * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires os.family != "windows" * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/PmapOnDebugdTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/PmapOnDebugdTest.java index b1665634fb0..c27989e20ca 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/PmapOnDebugdTest.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/PmapOnDebugdTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,6 +34,7 @@ import jtreg.SkippedException; * @test * @bug 8263670 * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires (os.family != "windows") & (os.family != "mac") * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/RunCommandOnServerTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/RunCommandOnServerTest.java index 9e725561341..5905d558c55 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/RunCommandOnServerTest.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/RunCommandOnServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 NTT DATA. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -37,6 +37,7 @@ import jtreg.SkippedException; * @bug 8265505 * @summary Test clhsdb command which should be run on debugd server * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires os.family != "windows" * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java index 69f4c9eb454..166e45cc3b7 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @summary Checks that the jshdb debugd utility successfully starts * and tries to attach to a running process * @requires vm.hasSA + * @requires vm.gc != "Z" * @requires (os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*")) * @requires os.family != "windows" * @modules java.base/jdk.internal.misc diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt index 065a52f9a83..a669f3e3abf 100644 --- a/test/jdk/ProblemList-zgc.txt +++ b/test/jdk/ProblemList-zgc.txt @@ -27,16 +27,6 @@ # ############################################################################# -# Quiet all SA tests - -sun/tools/jhsdb/HeapDumpTest.java 8307393 generic-all -sun/tools/jhsdb/BasicLauncherTest.java 8307393 generic-all -sun/tools/jhsdb/JStackStressTest.java 8307393 generic-all -sun/tools/jhsdb/JShellHeapDumpTest.java 8307393 generic-all -sun/tools/jhsdb/SAGetoptTest.java 8307393 generic-all -sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java 8307393 generic-all -sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java 8307393 generic-all - com/sun/jdi/ThreadMemoryLeakTest.java 8307402 generic-all ############################################################################# diff --git a/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java b/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java index 75f2af6db5a..412a811d219 100644 --- a/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java +++ b/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @summary Basic test for jhsdb launcher * @library /test/lib * @requires vm.hasSA + * @requires vm.gc != "Z" * @build jdk.test.lib.apps.* * @run main/timeout=480 BasicLauncherTest */ diff --git a/test/jdk/sun/tools/jhsdb/HeapDumpTest.java b/test/jdk/sun/tools/jhsdb/HeapDumpTest.java index c59e2b0e040..5ef1dadcb62 100644 --- a/test/jdk/sun/tools/jhsdb/HeapDumpTest.java +++ b/test/jdk/sun/tools/jhsdb/HeapDumpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8163346 * @summary Test hashing of extended characters in Serviceability Agent. * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @compile -encoding utf8 HeapDumpTest.java * @run main/timeout=240 HeapDumpTest diff --git a/test/jdk/sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java b/test/jdk/sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java index bd5a400225f..fffbe439f94 100644 --- a/test/jdk/sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java +++ b/test/jdk/sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8230731 8001227 8231635 8231634 8196969 * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @compile JShellHeapDumpTest.java * @run main/timeout=240 JShellHeapDumpTest nosleep diff --git a/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java b/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java index 6fbc96362a9..a9e5f7aeffe 100644 --- a/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java +++ b/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8225715 * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @compile JShellHeapDumpTest.java * @run main/timeout=240 JShellHeapDumpTest diff --git a/test/jdk/sun/tools/jhsdb/JStackStressTest.java b/test/jdk/sun/tools/jhsdb/JStackStressTest.java index 97945b6092b..a28cdf3be5a 100644 --- a/test/jdk/sun/tools/jhsdb/JStackStressTest.java +++ b/test/jdk/sun/tools/jhsdb/JStackStressTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8262271 * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @run main/timeout=240 JStackStressTest */ diff --git a/test/jdk/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java b/test/jdk/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java index 659eac2ee8f..b2c7ba0ef87 100644 --- a/test/jdk/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java +++ b/test/jdk/sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import jdk.test.lib.Utils; * @summary Unit test for jmap utility test heap configuration reader * * @requires vm.hasSA + * @requires vm.gc != "Z" * @library /test/lib * @modules java.management * jdk.hotspot.agent/sun.jvm.hotspot From 3d6856c251cb2476fe3d3139084d9c61c3835744 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 5 Mar 2026 17:25:54 +0000 Subject: [PATCH 078/170] 8374658: Consider use of "included" rather than "enclosed" in jx.a.p.Processor Reviewed-by: vromero --- .../annotation/processing/Processor.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java index 4be159868fa..2f2a9b285f6 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,28 +101,29 @@ import javax.lang.model.SourceVersion; * supports, possibly an empty set. * * For a given round, the tool computes the set of annotation - * interfaces that are present on the elements enclosed within the - * root elements. If there is at least one annotation interface - * present, then as processors claim annotation interfaces, they are - * removed from the set of unmatched annotation interfaces. When the - * set is empty or no more processors are available, the round has run - * to completion. If there are no annotation interfaces present, - * annotation processing still occurs but only universal + * interfaces that are present on the elements {@linkplain + * RoundEnvironment#getElementsAnnotatedWith(TypeElement) included} + * within the root elements. If there is at least one annotation + * interface present, then as processors claim annotation interfaces, + * they are removed from the set of unmatched annotation interfaces. + * When the set is empty or no more processors are available, the + * round has run to completion. If there are no annotation interfaces + * present, annotation processing still occurs but only universal * processors which support processing all annotation interfaces, * {@code "*"}, can claim the (empty) set of annotation interfaces. * *

    An annotation interface is considered present if there is at least - * one annotation of that interface present on an element enclosed within + * one annotation of that interface present on an element included within * the root elements of a round. For this purpose, a type parameter is - * considered to be enclosed by its {@linkplain + * considered to be included by its {@linkplain * TypeParameterElement#getGenericElement generic * element}. * For this purpose, a package element is not considered to - * enclose the top-level classes and interfaces within that + * include the top-level classes and interfaces within that * package. (A root element representing a package is created when a * {@code package-info} file is processed.) Likewise, for this - * purpose, a module element is not considered to enclose the + * purpose, a module element is not considered to include the * packages within that module. (A root element representing a module * is created when a {@code module-info} file is processed.) * From 3363a16c1d2725a0468e57690a3dcd27a0bf8a16 Mon Sep 17 00:00:00 2001 From: Sruthy Jayan Date: Thu, 5 Mar 2026 22:20:30 +0000 Subject: [PATCH 079/170] 8375045: Incorrect Interpretation of POSIX TZ Environment Variable on AIX Reviewed-by: naoto --- .../unix/native/libjava/TimeZone_md.c | 66 ++++++++++++------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/src/java.base/unix/native/libjava/TimeZone_md.c b/src/java.base/unix/native/libjava/TimeZone_md.c index cd253edde60..39e7b726220 100644 --- a/src/java.base/unix/native/libjava/TimeZone_md.c +++ b/src/java.base/unix/native/libjava/TimeZone_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -352,33 +352,15 @@ getPlatformTimeZoneID() } static char * -mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { +getJavaTimezoneFromPlatform(const char *tz_buf, size_t tz_len, const char *mapfilename) { FILE *tzmapf; - char mapfilename[PATH_MAX + 1]; char line[256]; int linecount = 0; - char *tz_buf = NULL; - char *temp_tz = NULL; char *javatz = NULL; - size_t tz_len = 0; - /* On AIX, the TZ environment variable may end with a comma - * followed by modifier fields until early AIX6.1. - * This restriction has been removed from AIX7. */ - - tz_buf = strdup(tz); - tz_len = strlen(tz_buf); - - /* Open tzmappings file, with buffer overrun check */ - if ((strlen(java_home_dir) + 15) > PATH_MAX) { - jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); - goto tzerr; - } - strcpy(mapfilename, java_home_dir); - strcat(mapfilename, "/lib/tzmappings"); if ((tzmapf = fopen(mapfilename, "r")) == NULL) { jio_fprintf(stderr, "can't open %s\n", mapfilename); - goto tzerr; + return NULL; } while (fgets(line, sizeof(line), tzmapf) != NULL) { @@ -431,10 +413,50 @@ mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { break; } } + (void) fclose(tzmapf); + return javatz; +} + +static char * +mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { + char mapfilename[PATH_MAX + 1]; + char *tz_buf = NULL; + char *javatz = NULL; + char *temp_tz = NULL; + size_t tz_len = 0; + + /* On AIX, the TZ environment variable may end with a comma + * followed by modifier fields until early AIX6.1. + * This restriction has been removed from AIX7. */ + + tz_buf = strdup(tz); + tz_len = strlen(tz_buf); + + /* Open tzmappings file, with buffer overrun check */ + if ((strlen(java_home_dir) + 15) > PATH_MAX) { + jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); + goto tzerr; + } + strcpy(mapfilename, java_home_dir); + strcat(mapfilename, "/lib/tzmappings"); + + // First attempt to find the Java timezone for the full tz string + javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); + + // If no match was found, check for timezone with truncated value + if (javatz == NULL) { + temp_tz = strchr(tz, ','); + tz_len = (temp_tz == NULL) ? strlen(tz) : temp_tz - tz; + free((void *) tz_buf); + tz_buf = (char *)malloc(tz_len + 1); + memcpy(tz_buf, tz, tz_len); + tz_buf[tz_len] = '\0'; + javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); + } tzerr: - if (tz_buf != NULL ) { + if (tz_buf != NULL) { free((void *) tz_buf); } From f266079d26ffc1541e5d3146258f7d39188d1a84 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 5 Mar 2026 23:54:52 +0000 Subject: [PATCH 080/170] 8378917: InputEvent checks for SystemClipboard access are unused Reviewed-by: dmarkov, serb --- .../share/classes/java/awt/AWTEvent.java | 15 +----------- .../classes/java/awt/event/InputEvent.java | 23 +------------------ .../share/classes/sun/awt/AWTAccessor.java | 7 ------ 3 files changed, 2 insertions(+), 43 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/AWTEvent.java b/src/java.desktop/share/classes/java/awt/AWTEvent.java index d48fae68cbe..f365393ffb1 100644 --- a/src/java.desktop/share/classes/java/awt/AWTEvent.java +++ b/src/java.desktop/share/classes/java/awt/AWTEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -554,22 +554,9 @@ public abstract class AWTEvent extends EventObject { */ void copyPrivateDataInto(AWTEvent that) { that.bdata = this.bdata; - // Copy canAccessSystemClipboard value from this into that. - if (this instanceof InputEvent && that instanceof InputEvent) { - - AWTAccessor.InputEventAccessor accessor - = AWTAccessor.getInputEventAccessor(); - - boolean b = accessor.canAccessSystemClipboard((InputEvent) this); - accessor.setCanAccessSystemClipboard((InputEvent) that, b); - } that.isSystemGenerated = this.isSystemGenerated; } void dispatched() { - if (this instanceof InputEvent) { - AWTAccessor.getInputEventAccessor(). - setCanAccessSystemClipboard((InputEvent) this, false); - } } } // class AWTEvent diff --git a/src/java.desktop/share/classes/java/awt/event/InputEvent.java b/src/java.desktop/share/classes/java/awt/event/InputEvent.java index 9f1172916df..7517ea810e3 100644 --- a/src/java.desktop/share/classes/java/awt/event/InputEvent.java +++ b/src/java.desktop/share/classes/java/awt/event/InputEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -309,13 +309,6 @@ public abstract sealed class InputEvent extends ComponentEvent */ int modifiers; - /* - * A flag that indicates that this instance can be used to access - * the system clipboard. - * This should be false in a headless environment, true in a headful one. - */ - private transient boolean canAccessSystemClipboard; - static { /* ensure that the necessary native libraries are loaded */ NativeLibLoader.loadLibraries(); @@ -328,15 +321,6 @@ public abstract sealed class InputEvent extends ComponentEvent return InputEvent.getButtonDownMasks(); } - public boolean canAccessSystemClipboard(InputEvent event) { - return event.canAccessSystemClipboard; - } - - @Override - public void setCanAccessSystemClipboard(InputEvent event, - boolean canAccessSystemClipboard) { - event.canAccessSystemClipboard = canAccessSystemClipboard; - } }); } @@ -381,11 +365,6 @@ public abstract sealed class InputEvent extends ComponentEvent super(source, id); this.when = when; this.modifiers = modifiers; - canAccessSystemClipboard = canAccessSystemClipboard(); - } - - private boolean canAccessSystemClipboard() { - return !GraphicsEnvironment.isHeadless(); } /** diff --git a/src/java.desktop/share/classes/sun/awt/AWTAccessor.java b/src/java.desktop/share/classes/sun/awt/AWTAccessor.java index c74219f7efa..f98118171b4 100644 --- a/src/java.desktop/share/classes/sun/awt/AWTAccessor.java +++ b/src/java.desktop/share/classes/sun/awt/AWTAccessor.java @@ -361,13 +361,6 @@ public final class AWTAccessor { * Accessor for InputEvent.getButtonDownMasks() */ int[] getButtonDownMasks(); - - /* - * Accessor for InputEvent.canAccessSystemClipboard field - */ - boolean canAccessSystemClipboard(InputEvent event); - void setCanAccessSystemClipboard(InputEvent event, - boolean canAccessSystemClipboard); } /** From c2f6bd87c6d3520c03caf5be75d35eec91f100bb Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 6 Mar 2026 01:08:49 +0000 Subject: [PATCH 081/170] 8379334: jpackage: fix bug in DottedVersion.greedy() function Reviewed-by: almatvee --- .../internal/model/DottedVersion.java | 86 ++++++++++---- .../internal/model/DottedVersionTest.java | 108 +++++++++++++++++- 2 files changed, 172 insertions(+), 22 deletions(-) diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/DottedVersion.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/DottedVersion.java index b49cbb025e9..8071f182801 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/DottedVersion.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/DottedVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,12 +37,11 @@ import java.util.stream.Stream; public final class DottedVersion { private DottedVersion(String version, boolean greedy) { - this.value = version; if (version.isEmpty()) { if (greedy) { throw new IllegalArgumentException(I18N.getString("error.version-string-empty")); } else { - this.components = new BigInteger[0]; + this.components = new Component[0]; this.suffix = ""; } } else { @@ -53,12 +52,12 @@ public final class DottedVersion { if (!greedy) { return null; } else { - ds.throwException(); + throw ds.createException(); } } try { - return new BigInteger(digits); + return new Component(digits); } catch (NumberFormatException ex) { if (!greedy) { return null; @@ -68,17 +67,25 @@ public final class DottedVersion { digits)); } } - }).takeWhile(Objects::nonNull).toArray(BigInteger[]::new); + }).takeWhile(Objects::nonNull).toArray(Component[]::new); suffix = ds.getUnprocessedString(); if (!suffix.isEmpty() && greedy) { - ds.throwException(); + throw ds.createException(); } } } + private DottedVersion(Component[] components, String suffix) { + this.components = components; + this.suffix = suffix; + } + private static class DigitsSupplier { DigitsSupplier(String input) { + if (input.isEmpty()) { + throw new IllegalArgumentException(); + } this.input = input; } @@ -95,7 +102,7 @@ public final class DottedVersion { } else { var curStopAtDot = (chr == '.'); if (!curStopAtDot) { - if (lastDotPos >= 0) { + if (sb.isEmpty() && lastDotPos >= 0) { cursor = lastDotPos; } else { cursor--; @@ -112,11 +119,7 @@ public final class DottedVersion { } if (sb.isEmpty()) { - if (lastDotPos >= 0) { - cursor = lastDotPos; - } else { - cursor--; - } + cursor = lastDotPos; } stoped = true; @@ -127,7 +130,7 @@ public final class DottedVersion { return input.substring(cursor); } - void throwException() { + IllegalArgumentException createException() { final String tail; if (lastDotPos >= 0) { tail = input.substring(lastDotPos + 1); @@ -143,7 +146,7 @@ public final class DottedVersion { errMessage = MessageFormat.format(I18N.getString( "error.version-string-invalid-component"), input, tail); } - throw new IllegalArgumentException(errMessage); + return new IllegalArgumentException(errMessage); } private int cursor; @@ -211,9 +214,31 @@ public final class DottedVersion { return Arrays.deepEquals(this.components, other.components); } + public DottedVersion trim(int limit) { + if (limit < 0) { + throw new IllegalArgumentException(); + } else if (limit >= components.length) { + return this; + } else { + return new DottedVersion(Arrays.copyOf(components, limit), suffix); + } + } + + public DottedVersion pad(int limit) { + if (limit < 0) { + throw new IllegalArgumentException(); + } else if (limit <= components.length) { + return this; + } else { + var newComponents = Arrays.copyOf(components, limit); + Arrays.fill(newComponents, components.length, newComponents.length, Component.ZERO); + return new DottedVersion(newComponents, suffix); + } + } + @Override public String toString() { - return value; + return Stream.of(components).map(Component::toString).collect(Collectors.joining(".")) + suffix; } public String getUnprocessedSuffix() { @@ -221,14 +246,35 @@ public final class DottedVersion { } public String toComponentsString() { - return Stream.of(components).map(BigInteger::toString).collect(Collectors.joining(".")); + return Stream.of(components).map(Component::parsedValue).map(BigInteger::toString).collect(Collectors.joining(".")); + } + + public int getComponentsCount() { + return components.length; } public BigInteger[] getComponents() { - return components; + return Stream.of(components).map(Component::parsedValue).toArray(BigInteger[]::new); } - private final BigInteger[] components; - private final String value; + private record Component(BigInteger parsedValue, String strValue) { + Component { + Objects.requireNonNull(parsedValue); + Objects.requireNonNull(strValue); + } + + Component(String strValue) { + this(new BigInteger(strValue), strValue); + } + + @Override + public String toString() { + return strValue; + } + + static final Component ZERO = new Component(BigInteger.ZERO, "0"); + } + + private final Component[] components; private final String suffix; } diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/DottedVersionTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/DottedVersionTest.java index 885ea31f726..df020f1a34c 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/DottedVersionTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/model/DottedVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertNotSame; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; @@ -108,12 +111,113 @@ public class DottedVersionTest { TestConfig.lazy("+1", "+1", 0, ""), TestConfig.lazy("-1", "-1", 0, ""), TestConfig.lazy("-0", "-0", 0, ""), - TestConfig.lazy("+0", "+0", 0, "") + TestConfig.lazy("+0", "+0", 0, ""), + TestConfig.lazy("+0", "+0", 0, ""), + TestConfig.lazy("1.2.3+ea", "+ea", 3, "1.2.3"), + TestConfig.lazy(".7", ".7", 0, ""), + TestConfig.lazy(".+7", ".+7", 0, "") )); return data; } + @ParameterizedTest + @MethodSource + public void testTrim(DottedVersion ver, String expectedStr, int limit) { + var expected = DottedVersion.lazy(expectedStr); + var actual = ver.trim(limit); + assertEquals(expected, actual); + if (limit >= ver.getComponents().length) { + assertSame(ver, actual); + } else { + assertNotSame(ver, actual); + } + assertEquals(expectedStr, actual.toString()); + } + + @ParameterizedTest + @MethodSource + public void testTrimNegative(DottedVersion ver, int limit) { + assertThrowsExactly(IllegalArgumentException.class, () -> { + ver.trim(limit); + }); + } + + private static Stream testTrim() { + + var testCases = new ArrayList(); + + for (var suffix : List.of("", ".foo", "-ea", "+345")) { + testCases.addAll(List.of( + Arguments.of("1.02.3" + suffix, "" + suffix, 0), + Arguments.of("1.02.3" + suffix, "1" + suffix, 1), + Arguments.of("1.02.3" + suffix, "1.02" + suffix, 2), + Arguments.of("1.02.3" + suffix, "1.02.3" + suffix, 3), + Arguments.of("1.02.3" + suffix, "1.02.3" + suffix, 4) + )); + } + + return testCases.stream().map(DottedVersionTest::mapFirstStringToDottedVersion); + } + + private static Stream testTrimNegative() { + return Stream.of( + Arguments.of("10.5.foo", -1) + ).map(DottedVersionTest::mapFirstStringToDottedVersion); + } + + @ParameterizedTest + @MethodSource + public void testPad(DottedVersion ver, String expectedStr, int limit) { + var expected = DottedVersion.lazy(expectedStr); + var actual = ver.pad(limit); + assertEquals(expected, actual); + if (limit <= ver.getComponents().length) { + assertSame(ver, actual); + } else { + assertNotSame(ver, actual); + } + assertEquals(expectedStr, actual.toString()); + } + + @ParameterizedTest + @MethodSource + public void testPadNegative(DottedVersion ver, int limit) { + assertThrowsExactly(IllegalArgumentException.class, () -> { + ver.pad(limit); + }); + } + + private static Stream testPad() { + + var testCases = new ArrayList(); + + for (var suffix : List.of("", ".foo", "-ea", "+345")) { + testCases.addAll(List.of( + Arguments.of("" + suffix, "" + suffix, 0), + Arguments.of("1.02.3" + suffix, "1.02.3" + suffix, 0), + Arguments.of("" + suffix, "0" + suffix, 1), + Arguments.of("1" + suffix, "1" + suffix, 1), + Arguments.of("1" + suffix, "1.0" + suffix, 2), + Arguments.of("1.02.3" + suffix, "1.02.3.0.0" + suffix, 5) + )); + } + + return testCases.stream().map(DottedVersionTest::mapFirstStringToDottedVersion); + } + + private static Stream testPadNegative() { + return Stream.of( + Arguments.of("10.5.foo", -1) + ).map(DottedVersionTest::mapFirstStringToDottedVersion); + } + + private static Arguments mapFirstStringToDottedVersion(Arguments v) { + var objs = v.get(); + objs[0] = DottedVersion.lazy((String)objs[0]); + return Arguments.of(objs); + } + record InvalidVersionTestSpec(String version, String invalidComponent) { public InvalidVersionTestSpec { Objects.requireNonNull(version); From 1a4825b2267ddeddd3772ecfb7ab2c9939cba632 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Fri, 6 Mar 2026 01:12:55 +0000 Subject: [PATCH 082/170] 8379158: Update FreeType to 2.14.2 Reviewed-by: azvegint, prr, serb --- src/java.desktop/share/legal/freetype.md | 2 +- .../include/freetype/config/ftoption.h | 8 +- .../include/freetype/config/mac-support.h | 2 + .../libfreetype/include/freetype/freetype.h | 25 +- .../libfreetype/include/freetype/ftbdf.h | 12 +- .../libfreetype/include/freetype/ftimage.h | 2 +- .../libfreetype/include/freetype/ftlcdfil.h | 10 +- .../libfreetype/include/freetype/ftparams.h | 7 +- .../include/freetype/internal/cfftypes.h | 4 +- .../include/freetype/internal/ftobjs.h | 30 +- .../libfreetype/include/freetype/t1tables.h | 4 +- .../native/libfreetype/src/autofit/afadjust.c | 13 +- .../native/libfreetype/src/autofit/afglobal.h | 4 +- .../native/libfreetype/src/autofit/aflatin.c | 64 +++-- .../native/libfreetype/src/autofit/afloader.c | 14 +- .../native/libfreetype/src/base/ftadvanc.c | 66 +++-- .../native/libfreetype/src/base/ftbitmap.c | 18 +- .../native/libfreetype/src/base/ftglyph.c | 15 +- .../native/libfreetype/src/base/ftlcdfil.c | 271 +----------------- .../native/libfreetype/src/base/ftobjs.c | 54 ++-- .../native/libfreetype/src/base/ftutil.c | 3 +- .../native/libfreetype/src/cff/cffdrivr.c | 4 +- .../native/libfreetype/src/cff/cffload.c | 4 +- .../native/libfreetype/src/cff/cffobjs.c | 6 +- .../native/libfreetype/src/cff/cfftoken.h | 4 +- .../native/libfreetype/src/cid/cidtoken.h | 2 +- .../native/libfreetype/src/pshinter/pshalgo.c | 240 ++-------------- .../native/libfreetype/src/pshinter/pshglob.c | 50 ++-- .../native/libfreetype/src/sfnt/pngshim.c | 5 +- .../native/libfreetype/src/sfnt/sfdriver.c | 7 +- .../native/libfreetype/src/sfnt/sfwoff2.c | 10 +- .../native/libfreetype/src/sfnt/ttcolr.c | 10 +- .../native/libfreetype/src/sfnt/ttsbit.c | 11 +- .../native/libfreetype/src/smooth/ftgrays.c | 4 +- .../native/libfreetype/src/smooth/ftsmooth.c | 165 ++++++++--- .../native/libfreetype/src/truetype/ttgload.c | 11 +- .../native/libfreetype/src/truetype/ttgxvar.c | 6 +- .../libfreetype/src/truetype/ttinterp.c | 16 +- .../libfreetype/src/truetype/ttinterp.h | 2 +- .../native/libfreetype/src/truetype/ttobjs.c | 23 +- .../native/libfreetype/src/type1/t1tokens.h | 2 +- 41 files changed, 400 insertions(+), 810 deletions(-) diff --git a/src/java.desktop/share/legal/freetype.md b/src/java.desktop/share/legal/freetype.md index cf2518df594..7259c27183f 100644 --- a/src/java.desktop/share/legal/freetype.md +++ b/src/java.desktop/share/legal/freetype.md @@ -1,4 +1,4 @@ -## The FreeType Project: Freetype v2.14.1 +## The FreeType Project: Freetype v2.14.2 ### FreeType Notice diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h index be7a4c50dc3..a0a1a410b68 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h @@ -759,7 +759,13 @@ FT_BEGIN_HEADER /************************************************************************** * * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an - * embedded 'BDF~' table within SFNT-based bitmap formats. + * embedded 'BDF~' table within an SFNT-based `.otb` font file. This table + * is an extension used by X11 to preserve BDF properties after conversion + * to SFNT containers. See + * + * https://fontforge.org/docs/techref/non-standard.html#non-standard-bdf + * + * for more details. */ /* #define TT_CONFIG_OPTION_BDF */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h index d1b6a9898fd..bd350851d56 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h @@ -24,6 +24,7 @@ * This is the only necessary change, so it is defined here instead * providing a new configuration file. */ +#ifdef FT_MACINTOSH #if defined( __APPLE__ ) || ( defined( __MWERKS__ ) && defined( macintosh ) ) /* No Carbon frameworks for 64bit 10.4.x. */ /* `AvailabilityMacros.h` is available since Mac OS X 10.2, */ @@ -36,6 +37,7 @@ ( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 ) #undef FT_MACINTOSH #endif +#endif /* __APPLE__ ... */ #elif defined( __SC__ ) || defined( __MRC__ ) /* Classic MacOS compilers */ diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h index 1e249235882..e8a1b1e2f3e 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h @@ -4318,14 +4318,13 @@ FT_BEGIN_HEADER * property `no-stem-darkening` provided by the 'autofit', 'cff', * 'type1', and 't1cid' modules; see @no-stem-darkening). * - * * @FT_PARAM_TAG_LCD_FILTER_WEIGHTS (LCD filter weights, corresponding - * to function @FT_Library_SetLcdFilterWeights). - * * * @FT_PARAM_TAG_RANDOM_SEED (seed value for the CFF, Type~1, and CID * 'random' operator, corresponding to the `random-seed` property * provided by the 'cff', 'type1', and 't1cid' modules; see * @random-seed). * + * * @FT_PARAM_TAG_LCD_FILTER_WEIGHTS (no longer supported). + * * Pass `NULL` as `data` in @FT_Parameter for a given tag to reset the * option and use the library or module default again. * @@ -4352,25 +4351,17 @@ FT_BEGIN_HEADER * FT_Bool darken_stems = 1; * * FT_Parameter property2; - * FT_LcdFiveTapFilter custom_weight = - * { 0x11, 0x44, 0x56, 0x44, 0x11 }; - * - * FT_Parameter property3; * FT_Int32 random_seed = 314159265; * - * FT_Parameter properties[3] = { property1, - * property2, - * property3 }; + * FT_Parameter properties[2] = { property1, + * property2 }; * * * property1.tag = FT_PARAM_TAG_STEM_DARKENING; * property1.data = &darken_stems; * - * property2.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; - * property2.data = custom_weight; - * - * property3.tag = FT_PARAM_TAG_RANDOM_SEED; - * property3.data = &random_seed; + * property2.tag = FT_PARAM_TAG_RANDOM_SEED; + * property2.data = &random_seed; * * FT_Face_Properties( face, 3, properties ); * ``` @@ -4381,7 +4372,7 @@ FT_BEGIN_HEADER * FT_Parameter property; * * - * property.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS; + * property.tag = FT_PARAM_TAG_STEM_DARKENING; * property.data = NULL; * * FT_Face_Properties( face, 1, &property ); @@ -5178,7 +5169,7 @@ FT_BEGIN_HEADER */ #define FREETYPE_MAJOR 2 #define FREETYPE_MINOR 14 -#define FREETYPE_PATCH 1 +#define FREETYPE_PATCH 2 /************************************************************************** diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h index faad25689c9..ab142249217 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h @@ -44,7 +44,8 @@ FT_BEGIN_HEADER * * @description: * This section contains the declaration of functions specific to BDF and - * PCF fonts. + * PCF fonts. They also work for SFNT bitmap fonts that contain a 'BDF~' + * table like X11's `.otb` fonts. * */ @@ -151,7 +152,9 @@ FT_BEGIN_HEADER * FreeType error code. 0~means success. * * @note: - * This function only works with BDF faces, returning an error otherwise. + * This function only works with BDF faces and SFNT fonts that have a + * 'BDF~' table, returning an error otherwise. For the latter, a bitmap + * strike size must be selected first. */ FT_EXPORT( FT_Error ) FT_Get_BDF_Charset_ID( FT_Face face, @@ -165,7 +168,7 @@ FT_BEGIN_HEADER * FT_Get_BDF_Property * * @description: - * Retrieve a BDF property from a BDF or PCF font file. + * Retrieve a BDF property from a BDF or PCF font. * * @input: * face :: @@ -196,6 +199,9 @@ FT_BEGIN_HEADER * * In case of error, `aproperty->type` is always set to * @BDF_PROPERTY_TYPE_NONE. + * + * This also works with SFNT fonts that have a 'BDF~' table, after a + * bitmap strike size has been selected. */ FT_EXPORT( FT_Error ) FT_Get_BDF_Property( FT_Face face, diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h index b0a0172ef4f..a4dc724f349 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h @@ -875,7 +875,7 @@ FT_BEGIN_HEADER */ typedef struct FT_Span_ { - short x; + unsigned short x; unsigned short len; unsigned char coverage; diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h index a0a8e9da929..37bb5e1b8fb 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h @@ -145,16 +145,10 @@ FT_BEGIN_HEADER * * FT_LCD_FILTER_LEGACY :: * FT_LCD_FILTER_LEGACY1 :: - * This filter corresponds to the original libXft color filter. It - * provides high contrast output but can exhibit really bad color - * fringes if glyphs are not extremely well hinted to the pixel grid. - * This filter is only provided for comparison purposes, and might be - * disabled or stay unsupported in the future. The second value is - * provided for compatibility with FontConfig, which historically used - * different enumeration, sometimes incorrectly forwarded to FreeType. + * The legacy libXft color filter is no longer supported and ignored. * * @since: - * 2.3.0 (`FT_LCD_FILTER_LEGACY1` since 2.6.2) + * 2.3.0 */ typedef enum FT_LcdFilter_ { diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h index 2c09db1683e..94dcd6399a6 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h @@ -133,11 +133,8 @@ FT_BEGIN_HEADER * FT_PARAM_TAG_LCD_FILTER_WEIGHTS * * @description: - * An @FT_Parameter tag to be used with @FT_Face_Properties. The - * corresponding argument specifies the five LCD filter weights for a - * given face (if using @FT_LOAD_TARGET_LCD, for example), overriding the - * global default values or the values set up with - * @FT_Library_SetLcdFilterWeights. + * Overriding global LCD filter weights with custom values for a given + * face is no longer supported and ignored. * * @since: * 2.8 diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h index 62335db4834..754122fa646 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h @@ -191,8 +191,8 @@ FT_BEGIN_HEADER FT_UInt weight; FT_Bool is_fixed_pitch; FT_Fixed italic_angle; - FT_Fixed underline_position; - FT_Fixed underline_thickness; + FT_Short underline_position; + FT_UShort underline_thickness; FT_Int paint_type; FT_Int charstring_type; FT_Matrix font_matrix; diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h index 3db2fe28ffd..d4d7bc00fe9 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h @@ -365,11 +365,6 @@ FT_BEGIN_HEADER * Value~0 means to use the font's value. Value~-1 means to use the * CFF driver's default. * - * lcd_weights :: - * lcd_filter_func :: - * These fields specify the LCD filtering weights and callback function - * for ClearType-style subpixel rendering. - * * refcount :: * A counter initialized to~1 at the time an @FT_Face structure is * created. @FT_Reference_Face increments this counter, and @@ -391,11 +386,6 @@ FT_BEGIN_HEADER FT_Char no_stem_darkening; FT_Int32 random_seed; -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */ - FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ -#endif - FT_Int refcount; } FT_Face_InternalRec; @@ -724,9 +714,9 @@ FT_BEGIN_HEADER const FT_Vector* origin ); /* Allocate a new bitmap buffer in a glyph slot. */ + /* Dimensions must be preset in advance. */ FT_BASE( FT_Error ) - ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, - FT_ULong size ); + ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot ); /* Set the bitmap buffer in a glyph slot to a given pointer. The buffer */ @@ -889,10 +879,6 @@ FT_BEGIN_HEADER * lcd_weights :: * The LCD filter weights for ClearType-style subpixel rendering. * - * lcd_filter_func :: - * The LCD filtering callback function for for ClearType-style subpixel - * rendering. - * * lcd_geometry :: * This array specifies LCD subpixel geometry and controls Harmony LCD * rendering technique, alternative to ClearType. @@ -926,7 +912,6 @@ FT_BEGIN_HEADER #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */ - FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */ #else FT_Vector lcd_geometry[3]; /* RGB subpixel positions */ #endif @@ -995,17 +980,6 @@ FT_BEGIN_HEADER #endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */ - /* Define default raster's interface. The default raster is located in */ - /* `src/base/ftraster.c'. */ - /* */ - /* Client applications can register new rasters through the */ - /* FT_Set_Raster() API. */ - -#ifndef FT_NO_DEFAULT_RASTER - FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster; -#endif - - /************************************************************************** * * @macro: diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h index fc3c1706de5..fe769f607fa 100644 --- a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h +++ b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h @@ -92,7 +92,7 @@ FT_BEGIN_HEADER FT_String* full_name; FT_String* family_name; FT_String* weight; - FT_Long italic_angle; + FT_Fixed italic_angle; FT_Bool is_fixed_pitch; FT_Short underline_position; FT_UShort underline_thickness; @@ -645,7 +645,7 @@ FT_BEGIN_HEADER PS_DICT_UNDERLINE_POSITION, /* FT_Short */ PS_DICT_UNDERLINE_THICKNESS, /* FT_UShort */ PS_DICT_FS_TYPE, /* FT_UShort */ - PS_DICT_ITALIC_ANGLE, /* FT_Long */ + PS_DICT_ITALIC_ANGLE, /* FT_Fixed */ PS_DICT_MAX = PS_DICT_ITALIC_ANGLE diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c index 6637cacfccf..a1aa45914d0 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afadjust.c @@ -1405,7 +1405,8 @@ FT_TRACE4(( " " )); idx = HB_SET_VALUE_INVALID; while ( hb( set_next )( gsub_lookups, &idx ) ) - if ( globals->gsub_lookups_single_alternate[idx] ) + if ( idx < globals->gsub_lookup_count && + globals->gsub_lookups_single_alternate[idx] ) { have_idx = TRUE; FT_TRACE4(( " %u", idx )); @@ -1428,9 +1429,17 @@ idx = HB_SET_VALUE_INVALID; while ( hb( set_next )( gsub_lookups, &idx ) ) { - FT_UInt32 offset = globals->gsub_lookups_single_alternate[idx]; + FT_UInt32 offset; + /* HarfBuzz only validates lookup indices while */ + /* processing lookups, not while collecting them, */ + /* so we have to do that by ourselves. */ + if ( idx < globals->gsub_lookup_count ) + offset = globals->gsub_lookups_single_alternate[idx]; + else + offset = 0; + /* Put all substitutions into a single hash table. Note that */ /* the hash values usually contain more than a single character */ /* code; this can happen if different 'SingleSubst' subtables */ diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h index 362f56e290b..dc061159492 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h @@ -116,7 +116,9 @@ FT_BEGIN_HEADER /* The GSUB table. */ FT_Byte* gsub; - /* Lookup offsets, with only SingleSubst and AlternateSubst non-NULL. */ + /* An array of lookup offsets (of `gsub_lookup_count` elements), */ + /* with only SingleSubst and AlternateSubst lookups non-NULL. */ + FT_UShort gsub_lookup_count; FT_UInt32* gsub_lookups_single_alternate; #endif diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c index cb5667ff793..4a42d919474 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c @@ -3269,9 +3269,9 @@ next_on = next_on->next; if ( next_on->y > p->y && prev_on->y > p->y ) - measurement = p->y - min_y; + measurement = SUB_LONG( p->y, min_y ); else if ( next_on->y < p->y && prev_on->y < p->y ) - measurement = max_y - p->y; + measurement = SUB_LONG( max_y, p->y ); else continue; @@ -3309,11 +3309,14 @@ p = first_point; do { - p = p->next; - /* We adjust the height of the diacritic only, which means */ - /* we are never dealing with large numbers and can thus avoid */ - /* `FT_MulFix`. */ - p->y = ( ( p->y - min_y ) * target_height / height ) + min_y; + p = p->next; + /* We adjust the height of the diacritic only, which means */ + /* we are never dealing with (valid) large numbers and can */ + /* thus avoid `FT_MulFix`. */ + p->y = ADD_LONG( MUL_LONG( SUB_LONG( p->y, + min_y ), + target_height ) / height, + min_y ); } while ( p != first_point ); @@ -3370,9 +3373,9 @@ next_on = next_on->next; if ( next_on->y > p->y && prev_on->y > p->y ) - measurement = p->y - min_y; + measurement = SUB_LONG( p->y, min_y ); else if ( next_on->y < p->y && prev_on->y < p->y ) - measurement = max_y - p->y; + measurement = SUB_LONG( max_y, p->y ); else continue; @@ -3403,8 +3406,11 @@ p = first_point; do { - p = p->next; - p->y = ( ( p->y - max_y ) * target_height / height ) + max_y; + p = p->next; + p->y = ADD_LONG( MUL_LONG( SUB_LONG( p->y, + max_y ), + target_height ) / height, + max_y ); } while ( p != first_point ); @@ -3462,9 +3468,9 @@ } while ( p != first_point ); /* Align bottom of the tilde to the grid. */ - min_y_rounded = FT_PIX_ROUND( min_y ); - delta = min_y_rounded - min_y; - height = max_y - min_y; + min_y_rounded = FT_PIX_ROUND_LONG( min_y ); + delta = SUB_LONG( min_y_rounded, min_y ); + height = SUB_LONG( max_y, min_y ); /* If the tilde is less than 3 pixels tall, snap the center of it */ /* to the grid instead of the bottom to improve readability. */ @@ -3502,9 +3508,9 @@ } while ( p != first_point ); - max_y_rounded = FT_PIX_ROUND( max_y ); - delta = max_y_rounded - max_y; - height = max_y - min_y; + max_y_rounded = FT_PIX_ROUND_LONG( max_y ); + delta = SUB_LONG( max_y_rounded, max_y ); + height = SUB_LONG( max_y, min_y ); if ( height < 64 * 3 ) delta -= ( FT_PIX_ROUND( height ) - height ) / 2; @@ -3673,7 +3679,7 @@ high_min_y = hints->contour_y_minima[high_contour]; high_max_y = hints->contour_y_maxima[high_contour]; - high_height = high_max_y - high_min_y; + high_height = SUB_LONG( high_max_y, high_min_y ); if ( high_height > accent_height_limit ) { @@ -3705,7 +3711,7 @@ /* We also check that the y minimum of the 'other' contour */ /* is below the high contour to avoid potential false hits */ /* with contours enclosed in the high one. */ - distance = high_min_y - max_y; + distance = SUB_LONG( high_min_y, max_y ); if ( distance < 64 && distance < min_distance && min_y < high_min_y ) @@ -3724,14 +3730,14 @@ tilde_min_y = hints->contour_y_minima[tilde_contour]; tilde_max_y = hints->contour_y_maxima[tilde_contour]; - tilde_height = tilde_max_y - tilde_min_y; + tilde_height = SUB_LONG( tilde_max_y, tilde_min_y); /* The vertical separation adjustment potentially undoes a */ /* tilde center alignment. If it would grid-align a tilde */ /* less than 3 pixels in height, shift additionally to */ /* re-center the tilde. */ - pos = high_min_y + adjustment_amount; + pos = ADD_LONG( high_min_y, adjustment_amount ); if ( adjust_below_top && is_top_tilde ) pos += high_height; @@ -3764,7 +3770,7 @@ { /* Value 8 is heuristic. */ FT_Pos height_delta = high_height / 8; - FT_Pos min_y_limit = high_min_y - height_delta; + FT_Pos min_y_limit = SUB_LONG( high_min_y, height_delta ); FT_TRACE4(( " Pushing high contour %ld units up\n", @@ -3784,7 +3790,7 @@ centering_adjustment )); af_move_contours_up( hints, - min_y_limit + high_height, + ADD_LONG( min_y_limit, high_height ), centering_adjustment ); } } @@ -3838,7 +3844,7 @@ low_min_y = hints->contour_y_minima[low_contour]; low_max_y = hints->contour_y_maxima[low_contour]; - low_height = low_max_y - low_min_y; + low_height = SUB_LONG( low_max_y, low_min_y ); if ( low_height > accent_height_limit ) { @@ -3863,7 +3869,7 @@ min_y = hints->contour_y_minima[contour]; max_y = hints->contour_y_maxima[contour]; - distance = min_y - low_max_y; + distance = SUB_LONG( min_y, low_max_y ); if ( distance < 64 && distance < min_distance && max_y > low_max_y ) @@ -3882,9 +3888,9 @@ tilde_min_y = hints->contour_y_minima[tilde_contour]; tilde_max_y = hints->contour_y_maxima[tilde_contour]; - tilde_height = tilde_max_y - tilde_min_y; + tilde_height = SUB_LONG( tilde_max_y, tilde_min_y ); - pos = low_max_y - adjustment_amount; + pos = SUB_LONG( low_max_y, adjustment_amount ); if ( adjust_above_bottom && is_bottom_tilde ) pos -= low_height; @@ -3915,7 +3921,7 @@ ( calculated_amount <= 66 || adjustment_amount <= 66 ) ) { FT_Pos height_delta = low_height / 8; - FT_Pos max_y_limit = low_max_y + height_delta; + FT_Pos max_y_limit = ADD_LONG( low_max_y, height_delta ); FT_TRACE4(( " Pushing low contour %ld units down\n", @@ -3929,7 +3935,7 @@ centering_adjustment )); af_move_contours_down( hints, - max_y_limit - low_height, + SUB_LONG( max_y_limit, low_height ), centering_adjustment ); } } diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c index d84adc09679..4e2ac1f1ce3 100644 --- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c +++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c @@ -524,16 +524,18 @@ bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); - bbox.xMax = FT_PIX_CEIL( bbox.xMax ); - bbox.yMax = FT_PIX_CEIL( bbox.yMax ); + bbox.xMax = FT_PIX_CEIL_LONG( bbox.xMax ); + bbox.yMax = FT_PIX_CEIL_LONG( bbox.yMax ); - slot->metrics.width = bbox.xMax - bbox.xMin; - slot->metrics.height = bbox.yMax - bbox.yMin; + slot->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin ); + slot->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin ); slot->metrics.horiBearingX = bbox.xMin; slot->metrics.horiBearingY = bbox.yMax; - slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x ); - slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y ); + slot->metrics.vertBearingX = FT_PIX_FLOOR( ADD_LONG( bbox.xMin, + vvector.x ) ); + slot->metrics.vertBearingY = FT_PIX_FLOOR( ADD_LONG( bbox.yMax, + vvector.y ) ); /* for mono-width fonts (like Andale, Courier, etc.) we need */ /* to keep the original rounded advance width; ditto for */ diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c index ff0fc510503..7b965c62d58 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c @@ -20,6 +20,7 @@ #include #include +#include static FT_Error @@ -47,11 +48,43 @@ /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */ for ( nn = 0; nn < count; nn++ ) - advances[nn] = FT_MulDiv( advances[nn], scale, 64 ); + advances[nn] = FT_MulFix( 1024 * advances[nn], scale ); return FT_Err_Ok; } + /* loading (and hinting) to calculate the advances is slow */ + /* unless TrueType hdmx table is provided as an accelerator */ + static FT_Error + ft_load_advances( FT_Face face, + FT_UInt gindex, + FT_UInt count, + FT_Int32 flags, + FT_Fixed *padvances ) + { + FT_UInt nn; + FT_Error error = FT_Err_Ok; + FT_Pos factor = flags & FT_LOAD_NO_SCALE ? 1 : 1024; + FT_Pos* advance = flags & FT_LOAD_VERTICAL_LAYOUT + ? &face->glyph->advance.y + : &face->glyph->advance.x; + + + flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; + + for ( nn = 0; nn < count; nn++ ) + { + error = FT_Load_Glyph( face, gindex + nn, flags ); + if ( error ) + break; + + /* scale from 26.6 to 16.16, unless NO_SCALE was requested */ + padvances[nn] = *advance * factor; + } + + return error; + } + /* at the moment, we can perform fast advance retrieval only in */ /* the following cases: */ @@ -102,7 +135,10 @@ return error; } - return FT_Get_Advances( face, gindex, 1, flags, padvance ); + if ( flags & FT_ADVANCE_FLAG_FAST_ONLY ) + return FT_THROW( Unimplemented_Feature ); + + return ft_load_advances( face, gindex, 1, flags, padvance ); } @@ -115,12 +151,9 @@ FT_Int32 flags, FT_Fixed *padvances ) { - FT_Error error = FT_Err_Ok; - FT_Face_GetAdvancesFunc func; - FT_UInt num, end, nn; - FT_Int factor; + FT_UInt num, end; if ( !face ) @@ -140,6 +173,9 @@ func = face->driver->clazz->get_advances; if ( func && LOAD_ADVANCE_FAST_CHECK( face, flags ) ) { + FT_Error error; + + error = func( face, start, count, flags, padvances ); if ( !error ) return ft_face_scale_advances_( face, padvances, count, flags ); @@ -148,26 +184,10 @@ return error; } - error = FT_Err_Ok; - if ( flags & FT_ADVANCE_FLAG_FAST_ONLY ) return FT_THROW( Unimplemented_Feature ); - flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; - factor = ( flags & FT_LOAD_NO_SCALE ) ? 1 : 1024; - for ( nn = 0; nn < count; nn++ ) - { - error = FT_Load_Glyph( face, start + nn, flags ); - if ( error ) - break; - - /* scale from 26.6 to 16.16, unless NO_SCALE was requested */ - padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) - ? face->glyph->advance.y * factor - : face->glyph->advance.x * factor; - } - - return error; + return ft_load_advances( face, start, count, flags, padvances ); } diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c index 2c8e44b905d..364f881e435 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c @@ -922,14 +922,7 @@ target->pitch = (int)final_width * 4; target->num_grays = 256; - if ( FT_LONG_MAX / target->pitch < (int)target->rows ) - { - FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%u x %u)\n", - final_width, final_rows )); - return FT_THROW( Invalid_Argument ); - } - - if ( FT_ALLOC( target->buffer, target->pitch * (int)target->rows ) ) + if ( FT_ALLOC_MULT( target->buffer, target->rows, target->pitch ) ) return error; free_target_bitmap_on_error = 1; @@ -950,16 +943,9 @@ new_pitch = (int)final_width * 4; - if ( FT_LONG_MAX / new_pitch < (int)final_rows ) - { - FT_TRACE5(( "FT_Blend_Bitmap: target bitmap too large (%u x %u)\n", - final_width, final_rows )); - return FT_THROW( Invalid_Argument ); - } - /* TODO: provide an in-buffer solution for large bitmaps */ /* to avoid allocation of a new buffer */ - if ( FT_ALLOC( buffer, new_pitch * (int)final_rows ) ) + if ( FT_ALLOC_MULT( buffer, final_rows, new_pitch ) ) goto Error; /* copy data to new buffer */ diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c index 75babb1aa56..6138cfeec2c 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c @@ -62,7 +62,7 @@ FT_GlyphSlot slot ) { FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; - FT_Error error = FT_Err_Ok; + FT_Error error; FT_Library library = FT_GLYPH( glyph )->library; @@ -75,17 +75,8 @@ glyph->left = slot->bitmap_left; glyph->top = slot->bitmap_top; - /* do lazy copying whenever possible */ - if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) - { - glyph->bitmap = slot->bitmap; - slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; - } - else - { - FT_Bitmap_Init( &glyph->bitmap ); - error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap ); - } + FT_Bitmap_Init( &glyph->bitmap ); + error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap ); Exit: return error; diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c index d026da8b012..51c6fd48a1b 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c @@ -25,265 +25,28 @@ #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING -/* define USE_LEGACY to implement the legacy filter */ -#define USE_LEGACY - -#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) ) - - - /* add padding according to filter weights */ + /* add padding sufficient for a 5-tap filter, */ + /* which is 2/3 of a pixel */ FT_BASE_DEF( void ) ft_lcd_padding( FT_BBox* cbox, FT_GlyphSlot slot, FT_Render_Mode mode ) { - FT_Byte* lcd_weights; - FT_Bitmap_LcdFilterFunc lcd_filter_func; + FT_UNUSED( slot ); - - /* Per-face LCD filtering takes priority if set up. */ - if ( slot->face && slot->face->internal->lcd_filter_func ) + if ( mode == FT_RENDER_MODE_LCD ) { - lcd_weights = slot->face->internal->lcd_weights; - lcd_filter_func = slot->face->internal->lcd_filter_func; + cbox->xMin -= 43; + cbox->xMax += 43; } - else + else if ( mode == FT_RENDER_MODE_LCD_V ) { - lcd_weights = slot->library->lcd_weights; - lcd_filter_func = slot->library->lcd_filter_func; - } - - if ( lcd_filter_func == ft_lcd_filter_fir ) - { - if ( mode == FT_RENDER_MODE_LCD ) - { - cbox->xMin -= lcd_weights[0] ? 43 : - lcd_weights[1] ? 22 : 0; - cbox->xMax += lcd_weights[4] ? 43 : - lcd_weights[3] ? 22 : 0; - } - else if ( mode == FT_RENDER_MODE_LCD_V ) - { - cbox->yMin -= lcd_weights[0] ? 43 : - lcd_weights[1] ? 22 : 0; - cbox->yMax += lcd_weights[4] ? 43 : - lcd_weights[3] ? 22 : 0; - } + cbox->yMin -= 43; + cbox->yMax += 43; } } - /* FIR filter used by the default and light filters */ - FT_BASE_DEF( void ) - ft_lcd_filter_fir( FT_Bitmap* bitmap, - FT_LcdFiveTapFilter weights ) - { - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - FT_Int pitch = bitmap->pitch; - FT_Byte* origin = bitmap->buffer; - FT_Byte mode = bitmap->pixel_mode; - - - /* take care of bitmap flow */ - if ( pitch > 0 && height > 0 ) - origin += pitch * (FT_Int)( height - 1 ); - - /* horizontal in-place FIR filter */ - if ( mode == FT_PIXEL_MODE_LCD && width >= 2 ) - { - FT_Byte* line = origin; - - - /* `fir' must be at least 32 bit wide, since the sum of */ - /* the values in `weights' can exceed 0xFF */ - - for ( ; height > 0; height--, line -= pitch ) - { - FT_UInt fir[5]; - FT_UInt val, xx; - - - val = line[0]; - fir[2] = weights[2] * val; - fir[3] = weights[3] * val; - fir[4] = weights[4] * val; - - val = line[1]; - fir[1] = fir[2] + weights[1] * val; - fir[2] = fir[3] + weights[2] * val; - fir[3] = fir[4] + weights[3] * val; - fir[4] = weights[4] * val; - - for ( xx = 2; xx < width; xx++ ) - { - val = line[xx]; - fir[0] = fir[1] + weights[0] * val; - fir[1] = fir[2] + weights[1] * val; - fir[2] = fir[3] + weights[2] * val; - fir[3] = fir[4] + weights[3] * val; - fir[4] = weights[4] * val; - - line[xx - 2] = FT_SHIFTCLAMP( fir[0] ); - } - - line[xx - 2] = FT_SHIFTCLAMP( fir[1] ); - line[xx - 1] = FT_SHIFTCLAMP( fir[2] ); - } - } - - /* vertical in-place FIR filter */ - else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 2 ) - { - FT_Byte* column = origin; - - - for ( ; width > 0; width--, column++ ) - { - FT_Byte* col = column; - FT_UInt fir[5]; - FT_UInt val, yy; - - - val = col[0]; - fir[2] = weights[2] * val; - fir[3] = weights[3] * val; - fir[4] = weights[4] * val; - col -= pitch; - - val = col[0]; - fir[1] = fir[2] + weights[1] * val; - fir[2] = fir[3] + weights[2] * val; - fir[3] = fir[4] + weights[3] * val; - fir[4] = weights[4] * val; - col -= pitch; - - for ( yy = 2; yy < height; yy++, col -= pitch ) - { - val = col[0]; - fir[0] = fir[1] + weights[0] * val; - fir[1] = fir[2] + weights[1] * val; - fir[2] = fir[3] + weights[2] * val; - fir[3] = fir[4] + weights[3] * val; - fir[4] = weights[4] * val; - - col[pitch * 2] = FT_SHIFTCLAMP( fir[0] ); - } - - col[pitch * 2] = FT_SHIFTCLAMP( fir[1] ); - col[pitch] = FT_SHIFTCLAMP( fir[2] ); - } - } - } - - -#ifdef USE_LEGACY - - /* intra-pixel filter used by the legacy filter */ - static void - _ft_lcd_filter_legacy( FT_Bitmap* bitmap, - FT_Byte* weights ) - { - FT_UInt width = (FT_UInt)bitmap->width; - FT_UInt height = (FT_UInt)bitmap->rows; - FT_Int pitch = bitmap->pitch; - FT_Byte* origin = bitmap->buffer; - FT_Byte mode = bitmap->pixel_mode; - - static const unsigned int filters[3][3] = - { - { 65538 * 9/13, 65538 * 1/6, 65538 * 1/13 }, - { 65538 * 3/13, 65538 * 4/6, 65538 * 3/13 }, - { 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 } - }; - - FT_UNUSED( weights ); - - - /* take care of bitmap flow */ - if ( pitch > 0 && height > 0 ) - origin += pitch * (FT_Int)( height - 1 ); - - /* horizontal in-place intra-pixel filter */ - if ( mode == FT_PIXEL_MODE_LCD && width >= 3 ) - { - FT_Byte* line = origin; - - - for ( ; height > 0; height--, line -= pitch ) - { - FT_UInt xx; - - - for ( xx = 0; xx < width; xx += 3 ) - { - FT_UInt r, g, b; - FT_UInt p; - - - p = line[xx]; - r = filters[0][0] * p; - g = filters[0][1] * p; - b = filters[0][2] * p; - - p = line[xx + 1]; - r += filters[1][0] * p; - g += filters[1][1] * p; - b += filters[1][2] * p; - - p = line[xx + 2]; - r += filters[2][0] * p; - g += filters[2][1] * p; - b += filters[2][2] * p; - - line[xx] = (FT_Byte)( r / 65536 ); - line[xx + 1] = (FT_Byte)( g / 65536 ); - line[xx + 2] = (FT_Byte)( b / 65536 ); - } - } - } - else if ( mode == FT_PIXEL_MODE_LCD_V && height >= 3 ) - { - FT_Byte* column = origin; - - - for ( ; width > 0; width--, column++ ) - { - FT_Byte* col = column - 2 * pitch; - - - for ( ; height > 0; height -= 3, col -= 3 * pitch ) - { - FT_UInt r, g, b; - FT_UInt p; - - - p = col[0]; - r = filters[0][0] * p; - g = filters[0][1] * p; - b = filters[0][2] * p; - - p = col[pitch]; - r += filters[1][0] * p; - g += filters[1][1] * p; - b += filters[1][2] * p; - - p = col[pitch * 2]; - r += filters[2][0] * p; - g += filters[2][1] * p; - b += filters[2][2] * p; - - col[0] = (FT_Byte)( r / 65536 ); - col[pitch] = (FT_Byte)( g / 65536 ); - col[pitch * 2] = (FT_Byte)( b / 65536 ); - } - } - } - } - -#endif /* USE_LEGACY */ - - /* documentation in ftlcdfil.h */ FT_EXPORT_DEF( FT_Error ) @@ -297,7 +60,6 @@ return FT_THROW( Invalid_Argument ); ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS ); - library->lcd_filter_func = ft_lcd_filter_fir; return FT_Err_Ok; } @@ -321,32 +83,23 @@ switch ( filter ) { case FT_LCD_FILTER_NONE: - library->lcd_filter_func = NULL; + ft_memset( library->lcd_weights, + 0, + FT_LCD_FILTER_FIVE_TAPS ); break; case FT_LCD_FILTER_DEFAULT: ft_memcpy( library->lcd_weights, default_weights, FT_LCD_FILTER_FIVE_TAPS ); - library->lcd_filter_func = ft_lcd_filter_fir; break; case FT_LCD_FILTER_LIGHT: ft_memcpy( library->lcd_weights, light_weights, FT_LCD_FILTER_FIVE_TAPS ); - library->lcd_filter_func = ft_lcd_filter_fir; break; -#ifdef USE_LEGACY - - case FT_LCD_FILTER_LEGACY: - case FT_LCD_FILTER_LEGACY1: - library->lcd_filter_func = _ft_lcd_filter_legacy; - break; - -#endif - default: return FT_THROW( Invalid_Argument ); } diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c index cced4fed06b..323dd5efac2 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c @@ -524,12 +524,28 @@ bitmap->rows = (unsigned int)height; bitmap->pitch = pitch; - if ( pbox.xMin < -0x8000 || pbox.xMax > 0x7FFF || - pbox.yMin < -0x8000 || pbox.yMax > 0x7FFF ) + /* Flag the bounding box size unsuitable for rendering. */ + /* FT_Renderer modules should check the return value. */ + /* The limit is based on the ppem value when available. */ { - FT_TRACE3(( "ft_glyphslot_preset_bitmap: [%ld %ld %ld %ld]\n", - pbox.xMin, pbox.yMin, pbox.xMax, pbox.yMax )); - return 1; + FT_Face face = slot->face; + FT_Pos xlim = 0x8000; + FT_Pos ylim = 0x8000; + + + if ( face ) + { + xlim = FT_MIN( xlim, 10 * face->size->metrics.x_ppem ); + ylim = FT_MIN( ylim, 10 * face->size->metrics.y_ppem ); + } + + if ( pbox.xMin < -xlim || pbox.xMax >= xlim || + pbox.yMin < -ylim || pbox.yMax >= ylim ) + { + FT_TRACE3(( "ft_glyphslot_preset_bitmap: [%ld %ld %ld %ld]\n", + pbox.xMin, pbox.yMin, pbox.xMax, pbox.yMax )); + return 1; + } } return 0; @@ -549,8 +565,7 @@ FT_BASE_DEF( FT_Error ) - ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, - FT_ULong size ) + ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot ) { FT_Memory memory = FT_FACE_MEMORY( slot->face ); FT_Error error; @@ -561,7 +576,10 @@ else slot->internal->flags |= FT_GLYPH_OWN_BITMAP; - FT_MEM_ALLOC( slot->bitmap.buffer, size ); + /* dimensions must be preset */ + FT_MEM_ALLOC_MULT( slot->bitmap.buffer, + slot->bitmap.rows, + slot->bitmap.pitch ); return error; } @@ -1413,7 +1431,10 @@ if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT && cur[0]->encoding_id == TT_MS_ID_UCS_4 ) || ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && - cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) ) + cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) || + ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && + cur[0]->encoding_id == TT_APPLE_ID_FULL_UNICODE && + FT_Get_CMap_Format( cur[0] ) == 13 ) ) { face->charmap = cur[0]; return FT_Err_Ok; @@ -2798,11 +2819,6 @@ internal->refcount = 1; internal->no_stem_darkening = -1; - -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - /* Per-face filtering can only be set up by FT_Face_Properties */ - internal->lcd_filter_func = NULL; -#endif } if ( aface ) @@ -4032,18 +4048,8 @@ } else if ( properties->tag == FT_PARAM_TAG_LCD_FILTER_WEIGHTS ) { -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - if ( properties->data ) - { - ft_memcpy( face->internal->lcd_weights, - properties->data, - FT_LCD_FILTER_FIVE_TAPS ); - face->internal->lcd_filter_func = ft_lcd_filter_fir; - } -#else error = FT_THROW( Unimplemented_Feature ); goto Exit; -#endif } else if ( properties->tag == FT_PARAM_TAG_RANDOM_SEED ) { diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c index 0b7382627c5..f83c4394893 100644 --- a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c +++ b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c @@ -424,11 +424,10 @@ while ( cur ) { FT_ListNode next = cur->next; - void* data = cur->data; if ( destroy ) - destroy( memory, data, user ); + destroy( memory, cur->data, user ); FT_FREE( cur ); cur = next; diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c index 0079ddd1950..44ff44aecbd 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c @@ -456,8 +456,8 @@ dict->weight ); font_info->italic_angle = dict->italic_angle; font_info->is_fixed_pitch = dict->is_fixed_pitch; - font_info->underline_position = (FT_Short)dict->underline_position; - font_info->underline_thickness = (FT_UShort)dict->underline_thickness; + font_info->underline_position = dict->underline_position; + font_info->underline_thickness = dict->underline_thickness; cff->font_info = font_info; } diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c index 326f885056f..39d662eb434 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c @@ -2014,8 +2014,8 @@ /* set defaults */ FT_ZERO( top ); - top->underline_position = -( 100L << 16 ); - top->underline_thickness = 50L << 16; + top->underline_position = -100; + top->underline_thickness = 50; top->charstring_type = 2; top->font_matrix.xx = 0x10000L; top->font_matrix.yy = 0x10000L; diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c index 1aeb908f4a1..9e00943a95d 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c @@ -846,10 +846,8 @@ cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); - cffface->underline_position = - (FT_Short)( dict->underline_position >> 16 ); - cffface->underline_thickness = - (FT_Short)( dict->underline_thickness >> 16 ); + cffface->underline_position = (FT_Short)dict->underline_position; + cffface->underline_thickness = (FT_Short)dict->underline_thickness; /* retrieve font family & style name */ if ( dict->family_name ) diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h index cc5aaa2867a..a7ee1cb3fe7 100644 --- a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h +++ b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h @@ -30,8 +30,8 @@ CFF_FIELD_STRING ( 4, weight, "Weight" ) CFF_FIELD_BOOL ( 0x101, is_fixed_pitch, "isFixedPitch" ) CFF_FIELD_FIXED ( 0x102, italic_angle, "ItalicAngle" ) - CFF_FIELD_FIXED ( 0x103, underline_position, "UnderlinePosition" ) - CFF_FIELD_FIXED ( 0x104, underline_thickness, "UnderlineThickness" ) + CFF_FIELD_NUM ( 0x103, underline_position, "UnderlinePosition" ) + CFF_FIELD_NUM ( 0x104, underline_thickness, "UnderlineThickness" ) CFF_FIELD_NUM ( 0x105, paint_type, "PaintType" ) CFF_FIELD_NUM ( 0x106, charstring_type, "CharstringType" ) CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" ) diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h index 25ba74fed94..d40ebfab86d 100644 --- a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h +++ b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h @@ -47,7 +47,7 @@ T1_FIELD_STRING( "FullName", full_name, 0 ) T1_FIELD_STRING( "FamilyName", family_name, 0 ) T1_FIELD_STRING( "Weight", weight, 0 ) - T1_FIELD_NUM ( "ItalicAngle", italic_angle, 0 ) + T1_FIELD_FIXED ( "ItalicAngle", italic_angle, 0 ) T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, 0 ) T1_FIELD_NUM ( "UnderlinePosition", underline_position, 0 ) T1_FIELD_NUM ( "UnderlineThickness", underline_thickness, 0 ) diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c index ca30702321d..e053dba17b2 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c @@ -35,10 +35,6 @@ #endif -#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */ - /* and similar glyphs */ - - /*************************************************************************/ /*************************************************************************/ /***** *****/ @@ -920,117 +916,6 @@ #define psh_corner_orientation ft_corner_orientation -#ifdef COMPUTE_INFLEXS - - /* compute all inflex points in a given glyph */ - static void - psh_glyph_compute_inflections( PSH_Glyph glyph ) - { - FT_UInt n; - - - for ( n = 0; n < glyph->num_contours; n++ ) - { - PSH_Point first, start, end, before, after; - FT_Pos in_x, in_y, out_x, out_y; - FT_Int orient_prev, orient_cur; - FT_Int finished = 0; - - - /* we need at least 4 points to create an inflection point */ - if ( glyph->contours[n].count < 4 ) - continue; - - /* compute first segment in contour */ - first = glyph->contours[n].start; - - start = end = first; - do - { - end = end->next; - if ( end == first ) - goto Skip; - - in_x = end->org_u - start->org_u; - in_y = end->org_v - start->org_v; - - } while ( in_x == 0 && in_y == 0 ); - - /* extend the segment start whenever possible */ - before = start; - do - { - do - { - start = before; - before = before->prev; - if ( before == first ) - goto Skip; - - out_x = start->org_u - before->org_u; - out_y = start->org_v - before->org_v; - - } while ( out_x == 0 && out_y == 0 ); - - orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y ); - - } while ( orient_prev == 0 ); - - first = start; - in_x = out_x; - in_y = out_y; - - /* now, process all segments in the contour */ - do - { - /* first, extend current segment's end whenever possible */ - after = end; - do - { - do - { - end = after; - after = after->next; - if ( after == first ) - finished = 1; - - out_x = after->org_u - end->org_u; - out_y = after->org_v - end->org_v; - - } while ( out_x == 0 && out_y == 0 ); - - orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y ); - - } while ( orient_cur == 0 ); - - if ( ( orient_cur ^ orient_prev ) < 0 ) - { - do - { - psh_point_set_inflex( start ); - start = start->next; - } - while ( start != end ); - - psh_point_set_inflex( start ); - } - - start = end; - end = after; - orient_prev = orient_cur; - in_x = out_x; - in_y = out_y; - - } while ( !finished ); - - Skip: - ; - } - } - -#endif /* COMPUTE_INFLEXS */ - - static void psh_glyph_done( PSH_Glyph glyph ) { @@ -1258,11 +1143,6 @@ glyph->outline = outline; glyph->globals = globals; -#ifdef COMPUTE_INFLEXS - psh_glyph_load_points( glyph, 0 ); - psh_glyph_compute_inflections( glyph ); -#endif /* COMPUTE_INFLEXS */ - /* now deal with hints tables */ error = psh_hint_table_init( &glyph->hint_tables [0], &ps_hints->dimension[0].hints, @@ -1285,122 +1165,47 @@ } - /* compute all extrema in a glyph for a given dimension */ + /* compute all extreme and inflection points */ + /* in a glyph for a given dimension */ static void psh_glyph_compute_extrema( PSH_Glyph glyph ) { FT_UInt n; - /* first of all, compute all local extrema */ for ( n = 0; n < glyph->num_contours; n++ ) { - PSH_Point first = glyph->contours[n].start; - PSH_Point point, before, after; + PSH_Point first, point, before, after; - if ( glyph->contours[n].count == 0 ) + /* we need at least 3 points to create an extremum */ + if ( glyph->contours[n].count < 3 ) continue; - point = first; - before = point; + first = glyph->contours[n].start; + point = first->prev; + after = first; do { - before = before->prev; - if ( before == first ) - goto Skip; - - } while ( before->org_u == point->org_u ); - - first = point = before->next; - - for (;;) - { - after = point; - do - { - after = after->next; - if ( after == first ) - goto Next; - - } while ( after->org_u == point->org_u ); - - if ( before->org_u < point->org_u ) - { - if ( after->org_u < point->org_u ) - { - /* local maximum */ - goto Extremum; - } - } - else /* before->org_u > point->org_u */ - { - if ( after->org_u > point->org_u ) - { - /* local minimum */ - Extremum: - do - { - psh_point_set_extremum( point ); - point = point->next; - - } while ( point != after ); - } - } - - before = after->prev; + before = point; point = after; + after = point->next; - } /* for */ + if ( ( before->org_u < point->org_u && point->org_u < after->org_u ) || + ( before->org_u > point->org_u && point->org_u > after->org_u ) ) + continue; - Next: - ; - } + /* otherwise this is either extremum or inflection point */ + psh_point_set_extremum( point ); - /* for each extremum, determine its direction along the */ - /* orthogonal axis */ - for ( n = 0; n < glyph->num_points; n++ ) - { - PSH_Point point, before, after; + /* also note its direction */ + if ( before->org_v < after->org_v ) + psh_point_set_positive( point ); + else if ( before->org_v > after->org_v ) + psh_point_set_negative( point ); - - point = &glyph->points[n]; - before = point; - after = point; - - if ( psh_point_is_extremum( point ) ) - { - do - { - before = before->prev; - if ( before == point ) - goto Skip; - - } while ( before->org_v == point->org_v ); - - do - { - after = after->next; - if ( after == point ) - goto Skip; - - } while ( after->org_v == point->org_v ); - } - - if ( before->org_v < point->org_v && - after->org_v > point->org_v ) - { - psh_point_set_positive( point ); - } - else if ( before->org_v > point->org_v && - after->org_v < point->org_v ) - { - psh_point_set_negative( point ); - } - - Skip: - ; + } while ( after != first ); } } @@ -1836,8 +1641,7 @@ point->dir_in != point->dir_out ) continue; - if ( !psh_point_is_extremum( point ) && - !psh_point_is_inflex( point ) ) + if ( !psh_point_is_extremum( point ) ) continue; point->flags &= ~PSH_POINT_SMOOTH; diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c index 521a5ff6c5c..a772b66f309 100644 --- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c +++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c @@ -376,36 +376,24 @@ /* not. We simply need to compare the vertical scale */ /* parameter to the raw bluescale value. Here is why: */ /* */ - /* We need to suppress overshoots for all pointsizes. */ - /* At 300dpi that satisfies: */ + /* The specs explain how the bluescale is calculated */ + /* from the desired maximum rounded pointsize at 300 dpi */ + /* and assuming upem of 1000. */ /* */ - /* pointsize < 240*bluescale + 0.49 */ + /* bluescale = ( pointsize - 0.49 ) / 240 */ /* */ - /* This corresponds to: */ + /* For unrounded pointsize in general terms */ /* */ - /* pixelsize < 1000*bluescale + 49/24 */ + /* bluescale = ( pointsize * dpi / 72 ) / upem */ /* */ - /* scale*EM_Size < 1000*bluescale + 49/24 */ + /* which is */ /* */ - /* However, for normal Type 1 fonts, EM_Size is 1000! */ - /* We thus only check: */ + /* bluescale = pixelsize / upem */ /* */ - /* scale < bluescale + 49/24000 */ + /* Therefore, the bluescale value can be used directly */ + /* as a scale limit, now that it is in comparable units */ /* */ - /* which we shorten to */ - /* */ - /* "scale < bluescale" */ - /* */ - /* Note that `blue_scale' is stored 1000 times its real */ - /* value, and that `scale' converts from font units to */ - /* fractional pixels. */ - /* */ - - /* 1000 / 64 = 125 / 8 */ - if ( scale >= 0x20C49BAL ) - blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 ); - else - blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 ); + blues->no_overshoots = FT_BOOL( scale < blues->blue_scale ); /* */ /* The blue threshold is the font units distance under */ @@ -420,8 +408,8 @@ FT_Int threshold = blues->blue_shift; - while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) - threshold--; + if ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) + threshold = 32 * 0x10000L / scale; blues->blue_threshold = threshold; } @@ -708,7 +696,6 @@ /* limit the BlueScale value to `1 / max_of_blue_zone_heights' */ { - FT_Fixed max_scale; FT_Short max_height = 1; @@ -725,11 +712,12 @@ priv->family_other_blues, max_height ); - /* BlueScale is scaled 1000 times */ - max_scale = FT_DivFix( 1000, max_height ); - globals->blues.blue_scale = priv->blue_scale < max_scale - ? priv->blue_scale - : max_scale; + /* restrict BlueScale value that is amplified 1000-fold and */ + /* rescale it to be comparable to the metrics scale */ + if ( FT_MulFix( max_height, priv->blue_scale ) < 1000 ) + globals->blues.blue_scale = priv->blue_scale * 8 / 125; + else + globals->blues.blue_scale = 64 * 0x10000L / max_height; } globals->blues.blue_shift = priv->blue_shift; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c index 9df75dc3acc..24fb3455598 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c @@ -420,10 +420,7 @@ if ( populate_map_and_metrics ) { /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */ - FT_ULong size = map->rows * (FT_ULong)map->pitch; - - - error = ft_glyphslot_alloc_bitmap( slot, size ); + error = ft_glyphslot_alloc_bitmap( slot ); if ( error ) goto DestroyExit; } diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c index ec78247aa56..32291e23e36 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c @@ -1142,12 +1142,7 @@ FT_Error error; - /* XXX: I don't know whether this is correct, since - * tt_face_find_bdf_prop only returns something correct if we have - * previously selected a size that is listed in the BDF table. - * Should we change the BDF table format to include single offsets - * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'? - */ + /* We expect that a bitmap strike has been selected. */ error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry ); if ( !error ) { diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c index 5acbbaa2a77..41c233597b8 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c @@ -1043,7 +1043,6 @@ FT_ULong total_n_points = 0; FT_UShort n_points_contour; FT_UInt j; - FT_ULong flag_size; FT_ULong triplet_size; FT_ULong triplet_bytes_used; FT_Bool have_overlap = FALSE; @@ -1088,8 +1087,8 @@ } substreams[N_POINTS_STREAM].offset = FT_STREAM_POS(); - flag_size = total_n_points; - if ( flag_size > substreams[FLAG_STREAM].size ) + points_size += total_n_points; + if ( points_size > substreams[FLAG_STREAM].size ) goto Fail; flags_buf = stream->base + substreams[FLAG_STREAM].offset; @@ -1106,8 +1105,7 @@ triplet_bytes_used = 0; /* Create array to store point information. */ - points_size = total_n_points; - if ( FT_QNEW_ARRAY( points, points_size ) ) + if ( FT_QNEW_ARRAY( points, total_n_points ) ) goto Fail; if ( triplet_decode( flags_buf, @@ -1118,7 +1116,7 @@ &triplet_bytes_used ) ) goto Fail; - substreams[FLAG_STREAM].offset += flag_size; + substreams[FLAG_STREAM].offset += total_n_points; substreams[GLYPH_STREAM].offset += triplet_bytes_used; if ( FT_STREAM_SEEK( substreams[GLYPH_STREAM].offset ) || diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c index ad9ad6f2710..7929b7aaf4c 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c @@ -1749,7 +1749,6 @@ FT_UInt x, y; FT_Byte b, g, r, alpha; - FT_ULong size; FT_Byte* src; FT_Byte* dst; @@ -1767,13 +1766,9 @@ dstSlot->bitmap.pitch = (int)dstSlot->bitmap.width * 4; dstSlot->bitmap.num_grays = 256; - size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch; - - error = ft_glyphslot_alloc_bitmap( dstSlot, size ); + error = ft_glyphslot_alloc_bitmap( dstSlot ); if ( error ) return error; - - FT_MEM_ZERO( dstSlot->bitmap.buffer, size ); } else { @@ -1805,8 +1800,7 @@ FT_Byte* q; - size = rows * pitch; - if ( FT_ALLOC( buf, size ) ) + if ( FT_ALLOC_MULT( buf, rows, pitch ) ) return error; p = dstSlot->bitmap.buffer; diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c index 9f9013bf39b..34e45619817 100644 --- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c +++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c @@ -547,7 +547,6 @@ FT_Error error = FT_Err_Ok; FT_UInt width, height; FT_Bitmap* map = decoder->bitmap; - FT_ULong size; if ( !decoder->metrics_loaded ) @@ -599,17 +598,11 @@ goto Exit; } - size = map->rows * (FT_ULong)map->pitch; - - /* check that there is no empty image */ - if ( size == 0 ) - goto Exit; /* exit successfully! */ - if ( metrics_only ) goto Exit; /* only metrics are requested */ - error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size ); - if ( error ) + error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph ); + if ( error || !map->buffer ) goto Exit; decoder->bitmap_allocated = 1; diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c index 365fbad42ad..3c387aea0ac 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c @@ -1804,7 +1804,7 @@ typedef ptrdiff_t FT_PtrDist; FT_FILL_RULE( coverage, cover, fill ); span[n].coverage = (unsigned char)coverage; - span[n].x = (short)x; + span[n].x = (unsigned short)x; span[n].len = (unsigned short)( cell->x - x ); if ( ++n == FT_MAX_GRAY_SPANS ) @@ -1823,7 +1823,7 @@ typedef ptrdiff_t FT_PtrDist; FT_FILL_RULE( coverage, area, fill ); span[n].coverage = (unsigned char)coverage; - span[n].x = (short)cell->x; + span[n].x = (unsigned short)cell->x; span[n].len = 1; if ( ++n == FT_MAX_GRAY_SPANS ) diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c index 21a6eca00ba..5a7a852a619 100644 --- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c +++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c @@ -80,6 +80,7 @@ { unsigned char* origin; /* pixmap origin at the bottom-left */ int pitch; /* pitch to go down one row */ + unsigned char wght[5]; /* filtering weights */ } TOrigin; @@ -274,6 +275,32 @@ } + /* This function applies a horizontal filter in direct rendering mode */ + static void + ft_smooth_lcd_spans( int y, + int count, + const FT_Span* spans, + void* target_ ) /* TOrigin* */ + { + TOrigin* target = (TOrigin*)target_; + + unsigned char* dst_line = target->origin - y * target->pitch - 2; + unsigned char* dst; + unsigned short w; + + + for ( ; count--; spans++ ) + for ( dst = dst_line + spans->x, w = spans->len; w--; dst++ ) + { + dst[0] += ( spans->coverage * target->wght[0] + 85 ) >> 8; + dst[1] += ( spans->coverage * target->wght[1] + 85 ) >> 8; + dst[2] += ( spans->coverage * target->wght[2] + 85 ) >> 8; + dst[3] += ( spans->coverage * target->wght[3] + 85 ) >> 8; + dst[4] += ( spans->coverage * target->wght[4] + 85 ) >> 8; + } + } + + static FT_Error ft_smooth_raster_lcd( FT_Renderer render, FT_Outline* outline, @@ -285,11 +312,47 @@ FT_Vector* vec; FT_Raster_Params params; + TOrigin target; - params.target = bitmap; - params.source = outline; - params.flags = FT_RASTER_FLAG_AA; + if ( render->root.library->lcd_weights[2] ) + { + /* Reject outlines that are too wide for 16-bit FT_Span. */ + /* Other limits are applied upstream with the same error code. */ + if ( bitmap->width > 0x7FFF ) + return FT_THROW( Raster_Overflow ); + + /* Set up direct rendering for instant filtering. */ + params.source = outline; + params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; + params.gray_spans = ft_smooth_lcd_spans; + params.user = ⌖ + + params.clip_box.xMin = 0; + params.clip_box.yMin = 0; + params.clip_box.xMax = bitmap->width; + params.clip_box.yMax = bitmap->rows; + + if ( bitmap->pitch < 0 ) + target.origin = bitmap->buffer; + else + target.origin = bitmap->buffer + + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch; + + target.pitch = bitmap->pitch; + + target.wght[0] = render->root.library->lcd_weights[0]; + target.wght[1] = render->root.library->lcd_weights[1]; + target.wght[2] = render->root.library->lcd_weights[2]; + target.wght[3] = render->root.library->lcd_weights[3]; + target.wght[4] = render->root.library->lcd_weights[4]; + } + else + { + params.target = bitmap; + params.source = outline; + params.flags = FT_RASTER_FLAG_AA; + } /* implode outline */ for ( vec = points; vec < points_end; vec++ ) @@ -306,6 +369,32 @@ } + /* This function applies a vertical filter in direct rendering mode */ + static void + ft_smooth_lcdv_spans( int y, + int count, + const FT_Span* spans, + void* target_ ) /* TOrigin* */ + { + TOrigin* target = (TOrigin*)target_; + + int pitch = target->pitch; + unsigned char* dst_line = target->origin - ( y + 2 ) * pitch; + unsigned char* dst; + unsigned short w; + + + for ( ; count--; spans++ ) + for ( dst = dst_line + spans->x, w = spans->len; w--; dst++ ) + { + dst[ 0] += ( spans->coverage * target->wght[0] + 85 ) >> 8; + dst[ pitch] += ( spans->coverage * target->wght[1] + 85 ) >> 8; + dst[2 * pitch] += ( spans->coverage * target->wght[2] + 85 ) >> 8; + dst[3 * pitch] += ( spans->coverage * target->wght[3] + 85 ) >> 8; + dst[4 * pitch] += ( spans->coverage * target->wght[4] + 85 ) >> 8; + } + } + static FT_Error ft_smooth_raster_lcdv( FT_Renderer render, FT_Outline* outline, @@ -317,11 +406,42 @@ FT_Vector* vec; FT_Raster_Params params; + TOrigin target; - params.target = bitmap; - params.source = outline; - params.flags = FT_RASTER_FLAG_AA; + if ( render->root.library->lcd_weights[2] ) + { + /* Set up direct rendering for instant filtering. */ + params.source = outline; + params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT; + params.gray_spans = ft_smooth_lcdv_spans; + params.user = ⌖ + + params.clip_box.xMin = 0; + params.clip_box.yMin = 0; + params.clip_box.xMax = bitmap->width; + params.clip_box.yMax = bitmap->rows; + + if ( bitmap->pitch < 0 ) + target.origin = bitmap->buffer; + else + target.origin = bitmap->buffer + + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch; + + target.pitch = bitmap->pitch; + + target.wght[0] = render->root.library->lcd_weights[0]; + target.wght[1] = render->root.library->lcd_weights[1]; + target.wght[2] = render->root.library->lcd_weights[2]; + target.wght[3] = render->root.library->lcd_weights[3]; + target.wght[4] = render->root.library->lcd_weights[4]; + } + else + { + params.target = bitmap; + params.source = outline; + params.flags = FT_RASTER_FLAG_AA; + } /* implode outline */ for ( vec = points; vec < points_end; vec++ ) @@ -494,12 +614,6 @@ else y_shift += 64 * (FT_Int)bitmap->rows; - if ( origin ) - { - x_shift += origin->x; - y_shift += origin->y; - } - /* translate outline to render it into the bitmap */ if ( x_shift || y_shift ) FT_Outline_Translate( outline, x_shift, y_shift ); @@ -527,33 +641,6 @@ error = ft_smooth_raster_lcd ( render, outline, bitmap ); else if ( mode == FT_RENDER_MODE_LCD_V ) error = ft_smooth_raster_lcdv( render, outline, bitmap ); - -#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING - - /* finally apply filtering */ - { - FT_Byte* lcd_weights; - FT_Bitmap_LcdFilterFunc lcd_filter_func; - - - /* Per-face LCD filtering takes priority if set up. */ - if ( slot->face && slot->face->internal->lcd_filter_func ) - { - lcd_weights = slot->face->internal->lcd_weights; - lcd_filter_func = slot->face->internal->lcd_filter_func; - } - else - { - lcd_weights = slot->library->lcd_weights; - lcd_filter_func = slot->library->lcd_filter_func; - } - - if ( lcd_filter_func ) - lcd_filter_func( bitmap, lcd_weights ); - } - -#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ - } Exit: diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c index e810ebfd550..4dd68ab1019 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c @@ -2217,6 +2217,10 @@ exec = size->context; #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL + /* reset backward compatibility; note that */ + /* the CVT program always runs without it */ + exec->backward_compatibility = 0; + if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) { grayscale = FALSE; @@ -2253,9 +2257,7 @@ return error; } - error = TT_Load_Context( exec, face, size ); - if ( error ) - return error; + TT_Load_Context( exec, face, size ); /* check whether the cvt program has disabled hinting */ if ( size->GS.instruct_control & 1 ) @@ -2283,8 +2285,7 @@ mode != FT_RENDER_MODE_MONO && !FT_IS_TRICKY( glyph->face ) ) exec->backward_compatibility = ( size->GS.instruct_control & 4 ) ^ 4; - else - exec->backward_compatibility = 0; + #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ loader->exec = exec; diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c index 0732fcbae36..f8842795f14 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c @@ -697,11 +697,9 @@ if ( long_words ) per_region_size *= 2; - if ( FT_NEW_ARRAY( varData->deltaSet, per_region_size * item_count ) ) + if ( FT_QALLOC_MULT( varData->deltaSet, item_count, per_region_size ) ) goto Exit; - if ( FT_Stream_Read( stream, - varData->deltaSet, - per_region_size * item_count ) ) + if ( FT_STREAM_READ( varData->deltaSet, item_count * per_region_size ) ) { FT_TRACE2(( "deltaSet read failed." )); error = FT_THROW( Invalid_Table ); diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c index 7b26c9a9df2..f46cc77fe5f 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c @@ -272,7 +272,7 @@ * * Note that not all members of `TT_ExecContext` get initialized. */ - FT_LOCAL_DEF( FT_Error ) + FT_LOCAL_DEF( void ) TT_Load_Context( TT_ExecContext exec, TT_Face face, TT_Size size ) @@ -284,7 +284,7 @@ exec->size = size; /* CVT and storage are not persistent in FreeType */ - /* reset them after they might have been modifief */ + /* reset them after they might have been modified */ exec->storage = exec->stack + exec->stackSize; exec->cvt = exec->storage + exec->storeSize; @@ -297,8 +297,6 @@ exec->metrics = *size->metrics; exec->twilight = size->twilight; - - return FT_Err_Ok; } @@ -5457,11 +5455,11 @@ /* single width cut-in test */ /* |org_dist - single_width_value| < single_width_cutin */ - if ( exc->GS.single_width_cutin > 0 && - org_dist < exc->GS.single_width_value + - exc->GS.single_width_cutin && - org_dist > exc->GS.single_width_value - - exc->GS.single_width_cutin ) + if ( exc->GS.single_width_cutin > 0 && + org_dist < ADD_LONG( exc->GS.single_width_value, + exc->GS.single_width_cutin ) && + org_dist > SUB_LONG( exc->GS.single_width_value, + exc->GS.single_width_cutin ) ) { if ( org_dist >= 0 ) org_dist = exc->GS.single_width_value; diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h index 2e69d191890..5cdc8f59f1a 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h @@ -439,7 +439,7 @@ FT_BEGIN_HEADER FT_LOCAL( void ) TT_Done_Context( TT_ExecContext exec ); - FT_LOCAL( FT_Error ) + FT_LOCAL( void ) TT_Load_Context( TT_ExecContext exec, TT_Face face, TT_Size size ); diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c index fd0c0ad14f6..2aedbd842c1 100644 --- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c +++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c @@ -884,9 +884,7 @@ FT_Error error; - error = TT_Load_Context( exec, face, size ); - if ( error ) - return error; + TT_Load_Context( exec, face, size ); /* disable CVT and glyph programs coderange */ TT_Clear_CodeRange( exec, tt_coderange_cvt ); @@ -952,9 +950,7 @@ FT_ARRAY_ZERO( size->twilight.org, size->twilight.n_points ); FT_ARRAY_ZERO( size->twilight.cur, size->twilight.n_points ); - error = TT_Load_Context( exec, face, size ); - if ( error ) - return error; + TT_Load_Context( exec, face, size ); /* clear storage area */ FT_ARRAY_ZERO( exec->storage, exec->storeSize ); @@ -1043,13 +1039,15 @@ if ( !exec ) return FT_THROW( Could_Not_Find_Context ); + size->context = exec; + exec->pedantic_hinting = pedantic; exec->maxFDefs = maxp->maxFunctionDefs; exec->maxIDefs = maxp->maxInstructionDefs; if ( FT_NEW_ARRAY( exec->FDefs, exec->maxFDefs + exec->maxIDefs ) ) - goto Exit; + goto Fail; exec->IDefs = exec->FDefs + exec->maxFDefs; @@ -1068,7 +1066,7 @@ if ( FT_NEW_ARRAY( exec->stack, exec->stackSize + (FT_Long)( exec->storeSize + exec->cvtSize ) ) ) - goto Exit; + goto Fail; /* reserve twilight zone and set GS before fpgm is executed, */ /* just in case, even though fpgm should not touch them */ @@ -1079,11 +1077,10 @@ error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); if ( error ) - goto Exit; + goto Fail; size->GS = tt_default_graphics_state; size->cvt_ready = -1; - size->context = exec; size->ttmetrics.rotated = FALSE; size->ttmetrics.stretched = FALSE; @@ -1099,10 +1096,8 @@ error = tt_size_run_fpgm( size ); return error; - Exit: - if ( error ) - tt_size_done_bytecode( size ); - + Fail: + tt_size_done_bytecode( size ); return error; } diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h index c3736cd42c0..a526406a411 100644 --- a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h +++ b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h @@ -33,7 +33,7 @@ T1_FIELD_DICT_FONTDICT ) /* we use pointers to detect modifications made by synthetic fonts */ - T1_FIELD_NUM ( "ItalicAngle", italic_angle, + T1_FIELD_FIXED ( "ItalicAngle", italic_angle, T1_FIELD_DICT_FONTDICT ) T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch, T1_FIELD_DICT_FONTDICT ) From c532dfff5332c27723c7d58cb86a4f8c34dfac1e Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 6 Mar 2026 03:33:16 +0000 Subject: [PATCH 083/170] 8379348: jpackage will use wrong arch suffix for RPM bundle when running on Debian Linux Reviewed-by: almatvee --- .../internal/LinuxBundlingEnvironment.java | 24 ++- .../jpackage/internal/LinuxDebPackager.java | 4 +- .../jpackage/internal/LinuxRpmPackager.java | 4 +- .../jpackage/internal/PackageProperty.java | 87 +++++----- .../resources/LinuxResources.properties | 4 +- .../test/JPackageStringBundleTest.java | 158 ++++++++++++++++++ .../jdk/jpackage/test/JPackageCommand.java | 83 ++++++++- .../jpackage/test/JPackageStringBundle.java | 99 ++++++++++- .../jdk/jpackage/test/LinuxHelper.java | 124 +++++++++----- .../jdk/jpackage/test/PropertyFinder.java | 10 +- .../cli/OptionsValidationFailTest.excludes | 12 +- .../jpackage/linux/LinuxResourceTest.java | 9 +- test/jdk/tools/jpackage/share/ErrorTest.java | 6 +- .../tools/jpackage/share/InstallDirTest.java | 5 +- 14 files changed, 507 insertions(+), 122 deletions(-) create mode 100644 test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java index d6d9def9407..724aeabb4b3 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxBundlingEnvironment.java @@ -33,6 +33,7 @@ import static jdk.jpackage.internal.cli.StandardBundlingOperation.CREATE_LINUX_R import static jdk.jpackage.internal.util.MemoizingSupplier.runOnce; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Stream; @@ -41,6 +42,7 @@ import jdk.jpackage.internal.cli.StandardBundlingOperation; import jdk.jpackage.internal.model.BundlingOperationDescriptor; import jdk.jpackage.internal.model.LinuxPackage; import jdk.jpackage.internal.model.PackageType; +import jdk.jpackage.internal.model.StandardPackageType; import jdk.jpackage.internal.util.Result; public class LinuxBundlingEnvironment extends DefaultBundlingEnvironment { @@ -55,11 +57,15 @@ public class LinuxBundlingEnvironment extends DefaultBundlingEnvironment { }); Supplier> debSysEnv = () -> { - return LinuxDebSystemEnvironment.create(sysEnv.get()); + return LinuxDebSystemEnvironment.create(sysEnv.get().flatMap(v -> { + return adjustPackageArch(v, StandardPackageType.LINUX_DEB); + })); }; Supplier> rpmSysEnv = () -> { - return LinuxRpmSystemEnvironment.create(sysEnv.get()); + return LinuxRpmSystemEnvironment.create(sysEnv.get().flatMap(v -> { + return adjustPackageArch(v, StandardPackageType.LINUX_RPM); + })); }; builder.defaultOperation(() -> { @@ -107,6 +113,20 @@ public class LinuxBundlingEnvironment extends DefaultBundlingEnvironment { return new BuildEnvFromOptions().predefinedAppImageLayout(APPLICATION_LAYOUT); } + private static Result adjustPackageArch(LinuxSystemEnvironment sysEnv, StandardPackageType type) { + Objects.requireNonNull(sysEnv); + Objects.requireNonNull(type); + if (sysEnv.nativePackageType().equals(type)) { + return Result.of(() -> { + return sysEnv; + }); + } else { + return LinuxPackageArch.create(type).map(arch -> { + return new LinuxSystemEnvironment.Stub(sysEnv.soLookupAvailable(), sysEnv.nativePackageType(), arch); + }); + } + } + private static final Map DESCRIPTORS = Stream.of( CREATE_LINUX_DEB, CREATE_LINUX_RPM diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java index 7c1f06f54a3..d46ec8865c8 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebPackager.java @@ -104,7 +104,7 @@ final class LinuxDebPackager extends LinuxPackager { List cmdline = new ArrayList<>(List.of( sysEnv.dpkgdeb().toString(), "-f", outputPackageFile().toString())); - properties.forEach(property -> cmdline.add(property.name)); + properties.forEach(property -> cmdline.add(property.name())); Map actualValues = Executor.of(cmdline) .saveOutput(true) @@ -116,7 +116,7 @@ final class LinuxDebPackager extends LinuxPackager { components -> components[1])); for (var property : properties) { - Optional.ofNullable(property.verifyValue(actualValues.get(property.name))).ifPresent(errors::add); + Optional.ofNullable(property.verifyValue(actualValues.get(property.name()))).ifPresent(errors::add); } return errors; diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmPackager.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmPackager.java index e22b9c24fdd..8c3e8125e9b 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmPackager.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmPackager.java @@ -112,12 +112,12 @@ final class LinuxRpmPackager extends LinuxPackager { "APPLICATION_VERSION", specFileName), new PackageProperty("Release", pkg.release().orElseThrow(), "APPLICATION_RELEASE", specFileName), - new PackageProperty("Arch", pkg.arch(), null, specFileName)); + new PackageProperty("Arch", pkg.arch(), specFileName)); var actualValues = Executor.of( sysEnv.rpm().toString(), "-qp", - "--queryformat", properties.stream().map(e -> String.format("%%{%s}", e.name)).collect(joining("\\n")), + "--queryformat", properties.stream().map(e -> String.format("%%{%s}", e.name())).collect(joining("\\n")), outputPackageFile().toString() ).saveOutput(true).executeExpectSuccess().getOutput(); diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/PackageProperty.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/PackageProperty.java index 6b06190f891..e19e45cb5d4 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/PackageProperty.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/PackageProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,52 +25,61 @@ package jdk.jpackage.internal; -import java.text.MessageFormat; +import java.util.Objects; +import java.util.Optional; import jdk.jpackage.internal.model.ConfigException; -final class PackageProperty { - /** - * Constructor - * - * @param name property name - * @param expectedValue expected property value - * @param substString substitution string to be placed in resource file to - * be replaced with the expected property value by jpackage at package build - * time - * @param customResource name of custom resource from resource directory in - * which this package property can be set - */ - PackageProperty(String name, String expectedValue, String substString, - String customResource) { - this.name = name; - this.expectedValue = expectedValue; - this.substString = substString; - this.customResource = customResource; +/** + * Linux package property. + * + * @param name the property name (e.g.: "Architecture", "Version") + * @param expectedValue the expected value of the property + * @param subtrituteString the substitute string in the jpackage resource if + * applicable (e.g.: "APPLICATION_PACKAGE", + * "APPLICATION_VERSION") + * @param resourceName the name of the custom resource file from the + * resource directory in which this package property can + * be set + */ +record PackageProperty(String name, String expectedValue, Optional subtrituteString, String customResource) { + + PackageProperty { + Objects.requireNonNull(name); + Objects.requireNonNull(expectedValue); + Objects.requireNonNull(subtrituteString); + Objects.requireNonNull(customResource); + } + + PackageProperty(String name, String expectedValue, String subtrituteString, String resourceName) { + this(name, expectedValue, Optional.of(subtrituteString), resourceName); + } + + PackageProperty(String name, String expectedValue, String resourceName) { + this(name, expectedValue, Optional.empty(), resourceName); + } + + private String formatErrorMessage(String actualValue) { + Objects.requireNonNull(actualValue); + return I18N.format("error.unexpected-package-property", + name, expectedValue, actualValue, customResource); + } + + private String formatAdvice(String actualValue) { + Objects.requireNonNull(actualValue); + return subtrituteString.map(ss -> { + return I18N.format("error.unexpected-package-property.advice", ss, actualValue, name, customResource); + }).orElseGet(() -> { + return I18N.format("error.unexpected-default-package-property.advice", name, customResource); + }); } ConfigException verifyValue(String actualValue) { + Objects.requireNonNull(actualValue); + if (expectedValue.equals(actualValue)) { return null; } - final String advice; - if (substString != null) { - advice = MessageFormat.format(I18N.getString( - "error.unexpected-package-property.advice"), substString, - actualValue, name, customResource); - } else { - advice = MessageFormat.format(I18N.getString( - "error.unexpected-default-package-property.advice"), name, - customResource); - } - - return new ConfigException(MessageFormat.format(I18N.getString( - "error.unexpected-package-property"), name, - expectedValue, actualValue, customResource, substString), advice); + return new ConfigException(formatErrorMessage(actualValue), formatAdvice(actualValue)); } - - final String name; - private final String expectedValue; - private final String substString; - private final String customResource; } diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties index 3aa0e0e92a0..1ab45d26a4c 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties @@ -58,6 +58,6 @@ message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get l warning.foreign-app-image=Warning: app-image dir not generated by jpackage. message.not-default-bundler-no-dependencies-lookup={0} is not the default package type. Package dependencies will not be generated. -error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property +error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like the value of "{0}" property is hardcoded in "{3}" file in the resource directory error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file -error.unexpected-default-package-property.advice=Don't explicitly set value of {0} property in custom "{1}" file +error.unexpected-default-package-property.advice=Don''t explicitly set value of "{0}" property in custom "{1}" file diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java new file mode 100644 index 00000000000..bf1eb2bdaec --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class JPackageStringBundleTest { + + @Test + void test_cannedFormattedString() { + assertFalse(JPackageStringBundle.MAIN.cannedFormattedString("error.version-string-empty").getValue().isBlank()); + } + + @Test + void test_cannedFormattedStringAsPattern() { + var pred = JPackageStringBundle.MAIN.cannedFormattedStringAsPattern("error.version-string-empty", UNREACHABLE_FORMAT_ARG_MAPPER).asMatchPredicate(); + + var str = JPackageStringBundle.MAIN.cannedFormattedString("error.version-string-empty").getValue(); + assertTrue(pred.test(str)); + assertFalse(pred.test(str + str)); + } + + @Test + void test_cannedFormattedStringAsPattern_with_arg() { + var pred = JPackageStringBundle.MAIN.cannedFormattedStringAsPattern("message.error-header", DEFAULT_FORMAT_ARG_MAPPER, "foo").asMatchPredicate(); + + for (var err : List.of("foo", "bar", "", "Unexpected value")) { + var str = JPackageStringBundle.MAIN.cannedFormattedString("message.error-header", err).getValue(); + assertTrue(pred.test(str)); + assertFalse(pred.test(err)); + } + } + + @ParameterizedTest + @MethodSource + void test_cannedFormattedString_wrong_argument_count(CannedFormattedString cannedStr) { + assertThrowsExactly(IllegalArgumentException.class, cannedStr::getValue); + } + + @Test + void test_cannedFormattedStringAsPattern_wrong_argument_count() { + assertThrowsExactly(IllegalArgumentException.class, () -> { + JPackageStringBundle.MAIN.cannedFormattedStringAsPattern("error.version-string-empty", UNREACHABLE_FORMAT_ARG_MAPPER, "foo"); + }); + + assertThrowsExactly(IllegalArgumentException.class, () -> { + JPackageStringBundle.MAIN.cannedFormattedStringAsPattern("message.error-header", UNREACHABLE_FORMAT_ARG_MAPPER); + }); + + assertThrowsExactly(IllegalArgumentException.class, () -> { + JPackageStringBundle.MAIN.cannedFormattedStringAsPattern("message.error-header", UNREACHABLE_FORMAT_ARG_MAPPER, "foo", "bar"); + }); + } + + @ParameterizedTest + @MethodSource + void test_toPattern(TestSpec test) { + var pattern = JPackageStringBundle.toPattern(new MessageFormat(test.formatter()), test.formatArgMapper(), test.args().toArray()); + assertEquals(test.expectedPattern().toString(), pattern.toString()); + } + + private static Collection test_cannedFormattedString_wrong_argument_count() { + return List.of( + JPackageStringBundle.MAIN.cannedFormattedString("error.version-string-empty", "foo"), + JPackageStringBundle.MAIN.cannedFormattedString("message.error-header"), + JPackageStringBundle.MAIN.cannedFormattedString("message.error-header", "foo", "bar") + ); + } + + private static Collection test_toPattern() { + + var testCases = new ArrayList(); + + testCases.addAll(List.of( + TestSpec.create("", Pattern.compile("")), + TestSpec.create("", Pattern.compile(""), "foo") + )); + + for (List args : List.of(List.of(), List.of("foo"))) { + Stream.of( + "Stop." + ).map(formatter -> { + return new TestSpec(formatter, args, Pattern.compile(Pattern.quote(formatter))); + }).forEach(testCases::add); + } + + testCases.add(TestSpec.create("Hello {1} {0}{1}!", Pattern.compile("\\QHello \\E.*\\Q \\E.*.*\\Q!\\E"), "foo", "bar")); + testCases.add(TestSpec.create("Hello {1} {0}{0} {0}{0}{0} {0}", Pattern.compile("\\QHello \\E.*\\Q \\E.*\\Q \\E.*\\Q \\E.*"), "foo", "bar")); + testCases.add(TestSpec.create("{0}{0}", Pattern.compile(".*"), "foo")); + + return testCases; + } + + record TestSpec(String formatter, List args, Pattern expectedPattern) { + TestSpec { + Objects.requireNonNull(formatter); + Objects.requireNonNull(args); + Objects.requireNonNull(expectedPattern); + } + + Function formatArgMapper() { + if (Pattern.compile(Pattern.quote(formatter)).toString().equals(expectedPattern.toString())) { + return UNREACHABLE_FORMAT_ARG_MAPPER; + } else { + return DEFAULT_FORMAT_ARG_MAPPER; + } + } + + static TestSpec create(String formatter, Pattern expectedPattern, Object... args) { + return new TestSpec(formatter, List.of(args), expectedPattern); + } + } + + private static final Pattern DEFAULT_FORMAT_ARG_PATTERN = Pattern.compile(".*"); + + private static final Function DEFAULT_FORMAT_ARG_MAPPER = _ -> { + return DEFAULT_FORMAT_ARG_PATTERN; + }; + + private static final Function UNREACHABLE_FORMAT_ARG_MAPPER = _ -> { + throw new AssertionError(); + }; +} 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 251d95a1089..2e58ea7a0ab 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -43,7 +43,6 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -245,7 +244,12 @@ public class JPackageCommand extends CommandArguments { } public String version() { - return getArgumentValue("--app-version", () -> "1.0"); + return PropertyFinder.findAppProperty(this, + PropertyFinder.cmdlineOptionWithValue("--app-version"), + PropertyFinder.appImageFile(appImageFile -> { + return appImageFile.version(); + }) + ).orElse("1.0"); } public String name() { @@ -1050,6 +1054,10 @@ public class JPackageCommand extends CommandArguments { final var directoriesAssert = new ReadOnlyPathsAssert(copy); + standardAssertOutputValidators().forEach(validator -> { + validator.applyTo(copy); + }); + Executor.Result result; if (expectedExitCode.isEmpty()) { result = copy.createExecutor().executeWithoutExitCodeCheck(); @@ -1064,7 +1072,7 @@ public class JPackageCommand extends CommandArguments { ConfigFilesStasher.INSTANCE.accept(this); } - for (final var validator: validators) { + for (final var validator: copy.validators) { validator.accept(result); } @@ -1375,10 +1383,38 @@ public class JPackageCommand extends CommandArguments { TKit.assertFileExists(cmd.appLayout().libapplauncher()); } }), + LINUX_PACKAGE_ARCH(cmd -> { + if (TKit.isLinux() && !cmd.isImagePackageType()) { + var asserter = TKit.assertTextStream(LinuxUnexpectedBundleArchRegexp.VALUE).negate(); + return Stream.of(true, false).map(stderr -> { + var validator = new JPackageOutputValidator(); + if (stderr) { + return validator.stderr(); + } else { + return validator; + } + }).map(validator -> { + return validator.add(asserter); + }).toList(); + } else { + return List.of(); + } + }), ; - StandardAssert(Consumer action) { + StandardAssert( + Consumer action, + Function> outputValidatorsSupplier) { this.action = action; + this.outputValidatorsSupplier = outputValidatorsSupplier; + } + + StandardAssert(Consumer action) { + this(Objects.requireNonNull(action), null); + } + + StandardAssert(Function> outputValidatorsSupplier) { + this(null, Objects.requireNonNull(outputValidatorsSupplier)); } private static JPackageCommand convertFromRuntime(JPackageCommand cmd) { @@ -1390,7 +1426,38 @@ public class JPackageCommand extends CommandArguments { return copy; } + Stream outputValidators(JPackageCommand cmd) { + Objects.requireNonNull(cmd); + return Optional.ofNullable(outputValidatorsSupplier).map(v -> { + return v.apply(cmd); + }).stream().flatMap(Collection::stream); + } + + void apply(JPackageCommand cmd) { + Objects.requireNonNull(cmd); + if (action != null) { + action.accept(cmd); + } + } + private final Consumer action; + private final Function> outputValidatorsSupplier; + + private static final class LinuxUnexpectedBundleArchRegexp { + private static final Pattern ANY = Pattern.compile(".*"); + private static final Pattern ARCHITECTURE_PROPERTY = Pattern.compile("Arch|Architecture"); + + static final Pattern VALUE = JPackageStringBundle.MAIN.cannedFormattedStringAsPattern("error.unexpected-package-property", arg -> { + return switch ((String)arg) { + case "propertyName" -> { + yield ARCHITECTURE_PROPERTY; + } + default -> { + yield ANY; + } + }; + }, "propertyName", "expectedValue", "actualValue", "customResource"); + } } public JPackageCommand setStandardAsserts(StandardAssert ... asserts) { @@ -1407,11 +1474,17 @@ public class JPackageCommand extends CommandArguments { JPackageCommand runStandardAsserts() { for (var standardAssert : standardAsserts.stream().sorted().toList()) { - standardAssert.action.accept(this); + standardAssert.apply(this); } return this; } + private List standardAssertOutputValidators() { + return standardAsserts.stream().sorted().flatMap(standardAssert -> { + return standardAssert.outputValidators(this); + }).toList(); + } + private boolean expectAppImageFile() { if (isRuntime()) { return false; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java index 9425b84472c..cd8ffd853b7 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,16 @@ package jdk.jpackage.test; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.MessageFormat; -import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import java.util.regex.Pattern; public enum JPackageStringBundle { @@ -56,18 +62,95 @@ public enum JPackageStringBundle { } private String getFormattedString(String key, Object[] args) { - var str = getString(key); - if (args.length != 0) { - return MessageFormat.format(str, args); - } else { - return str; - } + return new FormattedMessage(key, args).value(); } public CannedFormattedString cannedFormattedString(String key, Object ... args) { return new CannedFormattedString(this::getFormattedString, key, args); } + public Pattern cannedFormattedStringAsPattern(String key, Function formatArgMapper, Object ... args) { + var fm = new FormattedMessage(key, args); + return fm.messageFormat().map(mf -> { + return toPattern(mf, formatArgMapper, args); + }).orElseGet(() -> { + return Pattern.compile(Pattern.quote(fm.value())); + }); + } + + static Pattern toPattern(MessageFormat mf, Function formatArgMapper, Object ... args) { + Objects.requireNonNull(mf); + Objects.requireNonNull(formatArgMapper); + + var patternSb = new StringBuilder(); + var runSb = new StringBuilder(); + + var it = mf.formatToCharacterIterator(args); + while (it.getIndex() < it.getEndIndex()) { + var runBegin = it.getRunStart(); + var runEnd = it.getRunLimit(); + if (runEnd < runBegin) { + throw new IllegalStateException(); + } + + var attrs = it.getAttributes(); + if (attrs.isEmpty()) { + // Regular text run. + runSb.setLength(0); + it.setIndex(runBegin); + for (int counter = runEnd - runBegin; counter != 0; --counter) { + runSb.append(it.current()); + it.next(); + } + patternSb.append(Pattern.quote(runSb.toString())); + } else { + // Format run. + int argi = (Integer)attrs.get(MessageFormat.Field.ARGUMENT); + var arg = args[argi]; + var pattern = Objects.requireNonNull(formatArgMapper.apply(arg)); + patternSb.append(pattern.toString()); + it.setIndex(runEnd); + } + } + + return Pattern.compile(patternSb.toString()); + } + + private final class FormattedMessage { + + FormattedMessage(String key, Object[] args) { + List.of(args).forEach(Objects::requireNonNull); + + var formatter = getString(key); + + var mf = new MessageFormat(formatter); + var formatCount = mf.getFormatsByArgumentIndex().length; + if (formatCount != args.length) { + throw new IllegalArgumentException(String.format( + "Expected %d arguments for [%s] string, but given %d", formatCount, key, args.length)); + } + + if (formatCount == 0) { + this.mf = null; + value = formatter; + } else { + this.mf = mf; + value = mf.format(args); + } + } + + String value() { + return value; + } + + Optional messageFormat() { + return Optional.ofNullable(mf); + } + + private final String value; + private final MessageFormat mf; + } + private final Class i18nClass; private final Method i18nClass_getString; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index 78562b2ed26..66462bedfd7 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -26,6 +26,7 @@ import static java.util.Collections.unmodifiableSortedSet; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; +import static jdk.jpackage.internal.util.MemoizingSupplier.runOnce; import java.io.IOException; import java.io.UncheckedIOException; @@ -36,7 +37,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -46,35 +46,34 @@ import java.util.TreeMap; import java.util.TreeSet; import java.util.function.Function; import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; +import jdk.internal.util.Architecture; import jdk.jpackage.internal.util.PathUtils; +import jdk.jpackage.internal.util.Result; import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.LauncherShortcut.InvokeShortcutSpec; import jdk.jpackage.test.PackageTest.PackageHandlers; public final class LinuxHelper { - private static String getReleaseSuffix(JPackageCommand cmd) { - final String value; - final PackageType packageType = cmd.packageType(); - switch (packageType) { - case LINUX_DEB: - value = Optional.ofNullable(cmd.getArgumentValue( - "--linux-app-release", () -> null)).map(v -> "-" + v).orElse( - ""); - break; - case LINUX_RPM: - value = "-" + cmd.getArgumentValue("--linux-app-release", - () -> "1"); - break; - - default: - value = null; + static String getReleaseSuffix(JPackageCommand cmd) { + cmd.verifyIsOfType(PackageType.LINUX); + var release = Optional.ofNullable(cmd.getArgumentValue("--linux-app-release")); + switch (cmd.packageType()) { + case LINUX_DEB -> { + return release.map(v -> "-" + v).orElse(""); + } + case LINUX_RPM -> { + return "-" + release.orElse("1"); + } + default -> { + throw new UnsupportedOperationException(); + } } - return value; } public static String getPackageName(JPackageCommand cmd) { @@ -333,10 +332,14 @@ public final class LinuxHelper { long packageSize = getInstalledPackageSizeKB(cmd); TKit.trace("InstalledPackageSize: " + packageSize); TKit.assertNotEquals(0, packageSize, String.format( - "Check installed size of [%s] package in not zero", packageName)); + "Check installed size of [%s] package is not zero", packageName)); final boolean checkPrerequisites; - if (cmd.isRuntime()) { + if (NativePackageType.VALUE != cmd.packageType()) { + // Alien packaging (DEB packaging on RPM Linux or RPM packaging on Debian). + // Don't validate required packages. + checkPrerequisites = false; + } else if (cmd.isRuntime()) { Path runtimeDir = cmd.appRuntimeDirectory(); Set expectedCriticalRuntimePaths = CRITICAL_RUNTIME_FILES.stream().map( runtimeDir::resolve).collect(toSet()); @@ -850,29 +853,7 @@ public final class LinuxHelper { } public static String getDefaultPackageArch(PackageType type) { - if (archs == null) { - archs = new HashMap<>(); - } - - String arch = archs.get(type); - if (arch == null) { - final Executor exec; - switch (type) { - case LINUX_DEB: - exec = Executor.of("dpkg", "--print-architecture"); - break; - - case LINUX_RPM: - exec = Executor.of("rpmbuild", "--eval=%{_target_cpu}"); - break; - - default: - throw new UnsupportedOperationException(); - } - arch = exec.executeAndGetFirstLineOfOutput(); - archs.put(type, arch); - } - return arch; + return LinuxPackageArchitecture.get(type); } private static String getServiceUnitFileName(String packageName, String launcherName) { @@ -960,7 +941,62 @@ public final class LinuxHelper { static final Set CRITICAL_RUNTIME_FILES = Set.of(Path.of( "lib/server/libjvm.so")); - private static Map archs; + private enum LinuxPackageArchitecture implements Supplier { + RPM("rpmbuild", "--eval=%{_target_cpu}"), + DEB("dpkg", "--print-architecture"), + ; + + LinuxPackageArchitecture(String... cmdline) { + this.cmdline = List.of(cmdline); + } + + static String get(PackageType type) { + Objects.requireNonNull(type); + if (type.isSupported()) { + return ARCHS.get(type).get(); + } else { + return Architecture.current().name().toLowerCase(); + } + } + + @Override + public String get() { + return Executor.of(cmdline).executeAndGetFirstLineOfOutput(); + } + + private final List cmdline; + + private static final Map> ARCHS = Map.of( + PackageType.LINUX_RPM, runOnce(RPM), + PackageType.LINUX_DEB, runOnce(DEB)); + } + + private static final class NativePackageType { + + static final PackageType VALUE; + + private static boolean isDebian() { + // we are just going to run "dpkg -s coreutils" and assume Debian + // or derivative if no error is returned. + return Result.of(Executor.of("dpkg", "-s", "coreutils")::execute).hasValue(); + } + + private static boolean isRpm() { + // we are just going to run "rpm -q rpm" and assume RPM + // or derivative if no error is returned. + return Result.of(Executor.of("rpm", "-q", "rpm")::execute).hasValue(); + } + + static { + if (isDebian()) { + VALUE = PackageType.LINUX_DEB; + } else if (isRpm()) { + VALUE = PackageType.LINUX_RPM; + } else { + VALUE = null; + } + } + } private static final Pattern XDG_CMD_ICON_SIZE_PATTERN = Pattern.compile("\\s--size\\s+(\\d+)\\b"); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PropertyFinder.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PropertyFinder.java index 3d7ac490350..46425ceccbd 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PropertyFinder.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PropertyFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ package jdk.jpackage.test; + import static jdk.jpackage.test.AdditionalLauncher.getAdditionalLauncherProperties; import java.nio.file.Path; @@ -66,8 +67,13 @@ final class PropertyFinder { } static Finder nop() { + return of(Optional.empty()); + } + + static Finder of(Optional v) { + Objects.requireNonNull(v); return target -> { - return Optional.empty(); + return v; }; } diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes index f86fb9a3897..32968db0606 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.excludes @@ -28,16 +28,16 @@ ErrorTest.test(NATIVE; args-add=[--runtime-image, @@EMPTY_DIR@@]; errors=[messag ErrorTest.test(NATIVE; args-add=[--runtime-image, @@INVALID_MAC_RUNTIME_BUNDLE@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@INVALID_MAC_RUNTIME_BUNDLE@@, Contents/Home/lib/**/libjli.dylib]]) ErrorTest.test(NATIVE; args-add=[--runtime-image, @@INVALID_MAC_RUNTIME_IMAGE@@]; errors=[message.error-header+[error.invalid-runtime-image-missing-file, @@INVALID_MAC_RUNTIME_IMAGE@@, lib/**/libjli.dylib]]) ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 1.2.3.4.5]; errors=[message.error-header+[error.msi-product-version-components, 1.2.3.4.5], message.advice-header+[error.version-string-wrong-format.advice]]) -ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 1.2.65536]; errors=[message.error-header+[error.msi-product-version-build-out-of-range, 1.2.65536], message.advice-header+[error.version-string-wrong-format.advice]]) -ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 1.256]; errors=[message.error-header+[error.msi-product-version-minor-out-of-range, 1.256], message.advice-header+[error.version-string-wrong-format.advice]]) +ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 1.2.65536]; errors=[message.error-header+[error.msi-product-version-build-out-of-range], message.advice-header+[error.version-string-wrong-format.advice]]) +ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 1.256]; errors=[message.error-header+[error.msi-product-version-minor-out-of-range], message.advice-header+[error.version-string-wrong-format.advice]]) ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 1234]; errors=[message.error-header+[error.msi-product-version-components, 1234], message.advice-header+[error.version-string-wrong-format.advice]]) -ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 256.1]; errors=[message.error-header+[error.msi-product-version-major-out-of-range, 256.1], message.advice-header+[error.version-string-wrong-format.advice]]) +ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--app-version, 256.1]; errors=[message.error-header+[error.msi-product-version-major-out-of-range], message.advice-header+[error.version-string-wrong-format.advice]]) ErrorTest.test(WIN_EXE; app-desc=Hello; args-add=[--launcher-as-service]; errors=[message.error-header+[error.missing-service-installer], message.advice-header+[error.missing-service-installer.advice]]) ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 1.2.3.4.5]; errors=[message.error-header+[error.msi-product-version-components, 1.2.3.4.5], message.advice-header+[error.version-string-wrong-format.advice]]) -ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 1.2.65536]; errors=[message.error-header+[error.msi-product-version-build-out-of-range, 1.2.65536], message.advice-header+[error.version-string-wrong-format.advice]]) -ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 1.256]; errors=[message.error-header+[error.msi-product-version-minor-out-of-range, 1.256], message.advice-header+[error.version-string-wrong-format.advice]]) +ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 1.2.65536]; errors=[message.error-header+[error.msi-product-version-build-out-of-range], message.advice-header+[error.version-string-wrong-format.advice]]) +ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 1.256]; errors=[message.error-header+[error.msi-product-version-minor-out-of-range], message.advice-header+[error.version-string-wrong-format.advice]]) ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 1234]; errors=[message.error-header+[error.msi-product-version-components, 1234], message.advice-header+[error.version-string-wrong-format.advice]]) -ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 256.1]; errors=[message.error-header+[error.msi-product-version-major-out-of-range, 256.1], message.advice-header+[error.version-string-wrong-format.advice]]) +ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--app-version, 256.1]; errors=[message.error-header+[error.msi-product-version-major-out-of-range], message.advice-header+[error.version-string-wrong-format.advice]]) ErrorTest.test(WIN_MSI; app-desc=Hello; args-add=[--launcher-as-service]; errors=[message.error-header+[error.missing-service-installer], message.advice-header+[error.missing-service-installer.advice]]) ErrorTest.test(args-add=[@foo]; errors=[message.error-header+[ERR_CannotParseOptions, foo]]) ErrorTest.testMacSignWithoutIdentity(IMAGE; app-desc=Hello; args-add=[--mac-sign, --mac-signing-keychain, @@EMPTY_KEYCHAIN@@]; errors=[message.error-header+[error.cert.not.found, CODE_SIGN, EMPTY_KEYCHAIN]]) diff --git a/test/jdk/tools/jpackage/linux/LinuxResourceTest.java b/test/jdk/tools/jpackage/linux/LinuxResourceTest.java index b82706fc2c2..503c4db77fb 100644 --- a/test/jdk/tools/jpackage/linux/LinuxResourceTest.java +++ b/test/jdk/tools/jpackage/linux/LinuxResourceTest.java @@ -30,6 +30,7 @@ import java.util.Objects; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.CannedFormattedString; import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JPackageCommand.StandardAssert; import jdk.jpackage.test.JPackageOutputValidator; import jdk.jpackage.test.LinuxHelper; import jdk.jpackage.test.PackageTest; @@ -66,7 +67,7 @@ public class LinuxResourceTest { final var packageProp = property("Package", "dont-install-me"); final var verProp = property("Version", "1.2.3-R2"); - final var arhProp = property("Architecture", "bar"); + final var archProp = property("Architecture", "bar"); TKit.createTextFile(controlFile, List.of( packageProp.format(), @@ -74,13 +75,15 @@ public class LinuxResourceTest { "Section: APPLICATION_SECTION", "Maintainer: APPLICATION_MAINTAINER", "Priority: optional", - arhProp.format(), + archProp.format(), "Provides: dont-install-me", "Description: APPLICATION_DESCRIPTION", "Installed-Size: APPLICATION_INSTALLED_SIZE", "Depends: PACKAGE_DEFAULT_DEPENDENCIES" )); + cmd.excludeStandardAsserts(StandardAssert.LINUX_PACKAGE_ARCH); + new JPackageOutputValidator() .expectMatchingStrings(MAIN.cannedFormattedString( "message.using-custom-resource", @@ -92,7 +95,7 @@ public class LinuxResourceTest { packageProp.expectedValue(LinuxHelper.getPackageName(cmd)).token("APPLICATION_PACKAGE").resourceDirFile(controlFile).validateOutput(cmd); verProp.expectedValue(cmd.version()).token("APPLICATION_VERSION_WITH_RELEASE").resourceDirFile(controlFile).validateOutput(cmd); - arhProp.expectedValue(LinuxHelper.getDefaultPackageArch(cmd.packageType())).token("APPLICATION_ARCH").resourceDirFile(controlFile).validateOutput(cmd); + archProp.expectedValue(LinuxHelper.getDefaultPackageArch(cmd.packageType())).token("APPLICATION_ARCH").resourceDirFile(controlFile).validateOutput(cmd); }) .forTypes(PackageType.LINUX_RPM) .addInitializer(cmd -> { diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index 8bc7ba2521f..b325c02f039 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -945,13 +945,13 @@ public final class ErrorTest { .error("error.msi-product-version-components", "1.2.3.4.5") .advice("error.version-string-wrong-format.advice"), testSpec().type(type).addArgs("--app-version", "256.1") - .error("error.msi-product-version-major-out-of-range", "256.1") + .error("error.msi-product-version-major-out-of-range") .advice("error.version-string-wrong-format.advice"), testSpec().type(type).addArgs("--app-version", "1.256") - .error("error.msi-product-version-minor-out-of-range", "1.256") + .error("error.msi-product-version-minor-out-of-range") .advice("error.version-string-wrong-format.advice"), testSpec().type(type).addArgs("--app-version", "1.2.65536") - .error("error.msi-product-version-build-out-of-range", "1.2.65536") + .error("error.msi-product-version-build-out-of-range") .advice("error.version-string-wrong-format.advice") ); }).flatMap(x -> x).map(TestSpec.Builder::create).toList()); diff --git a/test/jdk/tools/jpackage/share/InstallDirTest.java b/test/jdk/tools/jpackage/share/InstallDirTest.java index 81d1fb3556e..4d5c1979190 100644 --- a/test/jdk/tools/jpackage/share/InstallDirTest.java +++ b/test/jdk/tools/jpackage/share/InstallDirTest.java @@ -102,10 +102,7 @@ public class InstallDirTest { .forTypes(PackageType.LINUX) .addInitializer(cmd -> { cmd.addArguments("--install-dir", installDir); - cmd.saveConsoleOutput(true); - }) - .addBundleVerifier((cmd, result) -> { - cmd.validateErr(JPackageCommand.makeError("error.invalid-install-dir")); + cmd.validateErr(JPackageCommand.makeError("error.invalid-install-dir", installDir)); }) .run(); } From ad0f078669505686a9f294000bfe7f8bc1611a37 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 6 Mar 2026 03:51:59 +0000 Subject: [PATCH 084/170] 8379341: jpackage: consolidate modular app tests Reviewed-by: almatvee --- .../tools/jpackage/share/ModularAppTest.java | 336 ++++++++++++++++++ .../tools/jpackage/share/ModulePathTest.java | 144 -------- .../tools/jpackage/share/ModulePathTest2.java | 74 ---- .../tools/jpackage/share/ModulePathTest3.java | 130 ------- .../jpackage/share/NoMPathRuntimeTest.java | 133 ------- 5 files changed, 336 insertions(+), 481 deletions(-) create mode 100644 test/jdk/tools/jpackage/share/ModularAppTest.java delete mode 100644 test/jdk/tools/jpackage/share/ModulePathTest.java delete mode 100644 test/jdk/tools/jpackage/share/ModulePathTest2.java delete mode 100644 test/jdk/tools/jpackage/share/ModulePathTest3.java delete mode 100644 test/jdk/tools/jpackage/share/NoMPathRuntimeTest.java diff --git a/test/jdk/tools/jpackage/share/ModularAppTest.java b/test/jdk/tools/jpackage/share/ModularAppTest.java new file mode 100644 index 00000000000..b14d70cc8f3 --- /dev/null +++ b/test/jdk/tools/jpackage/share/ModularAppTest.java @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import static jdk.jpackage.internal.util.MemoizingSupplier.runOnce; + +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.Objects; +import java.util.Optional; +import java.util.stream.Stream; +import javax.xml.xpath.XPathExpressionException; +import jdk.internal.util.OperatingSystem; +import jdk.jpackage.internal.util.MacBundle; +import jdk.jpackage.internal.util.Slot; +import jdk.jpackage.internal.util.TokenReplace; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.CannedFormattedString; +import jdk.jpackage.test.Executor; +import jdk.jpackage.test.HelloApp; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.JavaAppDesc; +import jdk.jpackage.test.JavaTool; +import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.TKit; + + +/* + * @test + * @summary jpackage bundling modular app + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @compile -Xlint:all -Werror ModularAppTest.java + * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * --jpt-run=ModularAppTest + */ + +public final class ModularAppTest { + + @Test + @ParameterSupplier + public void test(TestSpec spec) { + spec.run(); + } + + /** + * Test case for JDK-8233265. Adding modules in .jmod files for non-modular app + * results in unexpected jpackage failure. + */ + @Test + @Parameter("Hello!") + @Parameter("com.foo/com.foo.ModuleApp") + public void test8233265(String mainAppDesc) throws IOException { + JPackageCommand cmd = JPackageCommand.helloAppImage(mainAppDesc); + + // The test should make jpackage invoke jlink. + cmd.ignoreDefaultRuntime(true); + + var modulePath = Optional.ofNullable(cmd.getArgumentValue("--module-path")).map(Path::of).orElseGet(() -> { + var newModulePath = TKit.createTempDirectory("input-modules"); + cmd.addArguments("--module-path", newModulePath); + return newModulePath; + }); + + JavaAppDesc extraModule = JavaAppDesc.parse("x.jmod:com.x/com.x.Y"); + HelloApp.createBundle(extraModule, modulePath); + cmd.addArguments("--add-modules", extraModule.moduleName()); + + cmd.executeAndAssertHelloAppImageCreated(); + } + + /** + * Test case for JDK-8248254. App's module in the predefined runtime directory; + * no "--module-path" option on the command line. jpackage should find the app's + * module in the predefined runtime. + */ + @Test + @Parameter("IMAGE") + @Parameter(value = "MAC_BUNDLE", ifOS = OperatingSystem.MACOS) + public void test8248254(RuntimeType runtimeType) throws XPathExpressionException, IOException { + + final var appDesc = JavaAppDesc.parse("me.mymodule/me.mymodule.Main"); + + new JPackageCommand() + .setDefaultAppName() + .setPackageType(PackageType.IMAGE) + .setDefaultInputOutput() + .removeArgumentWithValue("--input") + .addArguments("--module", appDesc.moduleName() + "/" + appDesc.className()) + .setArgumentValue("--runtime-image", bakeModuleInRuntime(appDesc, runtimeType)) + .executeAndAssertHelloAppImageCreated(); + } + + /** + * Test case for JDK-8261518. App's module is baked into the predefined runtime + * image with jlink; no "--module-path" option on the command line. If there is + * a non-modular jar in the current directory, jpackage used to throw. + */ + @Test + @Parameter("IMAGE") + @Parameter(value = "MAC_BUNDLE", ifOS = OperatingSystem.MACOS) + public void test8261518(RuntimeType runtimeType) throws XPathExpressionException, IOException { + + final var appDesc = JavaAppDesc.parse("com.foo/com.foo.main.Aloha"); + + final var fooJarDir = TKit.createTempDirectory("foo"); + + // Create "foo.jar" in dedicated directory. + HelloApp.createBundle(JavaAppDesc.parse("foo.jar:"), fooJarDir); + + new JPackageCommand() + .setDefaultAppName() + .setPackageType(PackageType.IMAGE) + .setDefaultInputOutput() + .removeArgumentWithValue("--input") + .addArguments("--module", appDesc.moduleName() + "/" + appDesc.className()) + .setArgumentValue("--runtime-image", bakeModuleInRuntime(appDesc, runtimeType).toAbsolutePath()) + // Run jpackage in the directory with "foo.jar" + .setDirectory(fooJarDir).useToolProvider(false) + .executeAndAssertHelloAppImageCreated(); + } + + private static Path bakeModuleInRuntime(JavaAppDesc appDesc, RuntimeType runtimeType) throws IOException { + + final var moduleOutputDir = TKit.createTempDirectory("modules"); + HelloApp.createBundle(appDesc, moduleOutputDir); + + final var workDir = TKit.createTempDirectory("runtime").resolve("data"); + final Path jlinkOutputDir; + switch (runtimeType) { + case IMAGE -> { + jlinkOutputDir = workDir; + } + case MAC_BUNDLE -> { + var macBundle = new MacBundle(workDir); + + // Create macOS bundle structure sufficient to pass jpackage validation. + Files.createDirectories(macBundle.homeDir().getParent()); + Files.createDirectories(macBundle.macOsDir()); + Files.createFile(macBundle.infoPlistFile()); + jlinkOutputDir = macBundle.homeDir(); + } + default -> { + throw new AssertionError(); + } + } + + // List of modules required for the test app. + final var modules = new String[] { + "java.base", + "java.desktop", + appDesc.moduleName() + }; + + new Executor() + .setToolProvider(JavaTool.JLINK) + .dumpOutput() + .addArguments( + "--add-modules", String.join(",", modules), + "--output", jlinkOutputDir.toString(), + "--module-path", moduleOutputDir.resolve(appDesc.jarFileName()).toString(), + "--strip-debug", + "--no-header-files", + "--no-man-pages", + "--strip-native-commands") + .execute(); + + return workDir; + } + + enum RuntimeType { + IMAGE, + MAC_BUNDLE, + ; + } + + record TestSpec(List paths, String appDesc) { + TestSpec { + Objects.requireNonNull(paths); + Objects.requireNonNull(appDesc); + Objects.requireNonNull(JavaAppDesc.parse(appDesc).moduleName()); + } + + boolean isWithGoodPath() { + var isWithGoodPath = Slot.createEmpty(); + paths.forEach(path -> { + ALL_TOKENS.applyTo(path, token -> { + if (token.equals(Token.GOOD_DIR.token())) { + isWithGoodPath.set(true); + } + return token; + }); + }); + return isWithGoodPath.find().isPresent(); + } + + void run() { + var emptyDir = runOnce(() -> { + return TKit.createTempDirectory("empty-dir"); + }); + + var nonExistingDir = runOnce(() -> { + return TKit.withTempDirectory("non-existing-dir", x -> {}); + }); + + var goodDir = runOnce(() -> { + return TKit.createTempDirectory("modules"); + }); + + var theAppDesc = JavaAppDesc.parse(appDesc); + + HelloApp.createBundle(theAppDesc, goodDir.get()); + + var cmd = new JPackageCommand() + .setArgumentValue("--dest", TKit.workDir().resolve("output")) + .setDefaultAppName() + .setPackageType(PackageType.IMAGE) + // Ignore runtime that can be set for all tests. Usually if default + // runtime is set, it is fake one to save time on running jlink and + // copying megabytes of data from Java home to application image. + // We need proper runtime for this test. + .ignoreDefaultRuntime(true) + .addArguments("--module", String.join("/", theAppDesc.moduleName(), theAppDesc.className())); + + if (TKit.isWindows()) { + cmd.addArguments("--win-console"); + } + + paths.stream().map(path -> { + return ALL_TOKENS.applyTo(path, token -> { + return (switch (Token.valueOf(token.substring(2, token.length() - 2))) { + case EMPTY_DIR -> { + yield emptyDir; + } + case GOOD_DIR -> { + yield goodDir; + } + case NON_EXISTING_DIR -> { + yield nonExistingDir; + } + default -> { + throw new AssertionError(); + } + }).get(); + }); + }).mapMulti((path, acc) -> { + acc.accept("--module-path"); + acc.accept(path); + }).forEach(cmd::addArgument); + + if (isWithGoodPath()) { + cmd.executeAndAssertHelloAppImageCreated(); + } else { + final CannedFormattedString expectedErrorMessage; + if (paths.isEmpty()) { + expectedErrorMessage = JPackageCommand.makeError( + "ERR_MissingArgument2", "--runtime-image", "--module-path"); + } else { + expectedErrorMessage = JPackageCommand.makeError( + "error.no-module-in-path", theAppDesc.moduleName()); + } + + cmd.validateErr(expectedErrorMessage).execute(1); + } + } + + private static final TokenReplace ALL_TOKENS = + new TokenReplace(Stream.of(Token.values()).map(Token::token).toArray(String[]::new)); + } + + public static Collection test() { + + var testCases = new ArrayList(); + + for (String appDesc : List.of( + "benvenuto.jar:com.jar.foo/com.jar.foo.Hello", + "benvenuto.jmod:com.jmod.foo/com.jmod.foo.JModHello" + )) { + Stream.>of( + Stream.of(Token.GOOD_DIR, Token.EMPTY_DIR, Token.NON_EXISTING_DIR).map(Token::token), + Stream.of(Token.EMPTY_DIR, Token.NON_EXISTING_DIR, Token.GOOD_DIR).map(Token::token), + Stream.of(Token.GOOD_DIR.token() + "/a/b/c/d", Token.GOOD_DIR.token()), + Stream.of(), + Stream.of(Token.EMPTY_DIR).map(Token::token) + ).map(Stream::toList).map(paths -> { + return new TestSpec(paths, appDesc); + }).forEach(testCases::add); + } + + return testCases.stream().map(v -> { + return new Object[] {v}; + }).toList(); + } + + enum Token { + GOOD_DIR, + EMPTY_DIR, + NON_EXISTING_DIR, + ; + + String token() { + return makeToken(name()); + } + + private static String makeToken(String v) { + Objects.requireNonNull(v); + return String.format("@@%s@@", v); + } + } +} diff --git a/test/jdk/tools/jpackage/share/ModulePathTest.java b/test/jdk/tools/jpackage/share/ModulePathTest.java deleted file mode 100644 index 583dd1eb0c4..00000000000 --- a/test/jdk/tools/jpackage/share/ModulePathTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Collection; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import jdk.jpackage.test.CannedFormattedString; -import jdk.jpackage.test.TKit; -import jdk.jpackage.test.JavaAppDesc; -import jdk.jpackage.test.HelloApp; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.JPackageStringBundle; -import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Parameters; -import jdk.jpackage.test.Annotations.Test; - - -/* - * @test - * @summary jpackage with --module-path testing - * @library /test/jdk/tools/jpackage/helpers - * @build jdk.jpackage.test.* - * @compile -Xlint:all -Werror ModulePathTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=ModulePathTest - */ - -public final class ModulePathTest { - - @Parameters - public static Collection data() { - return List.of(new String[][]{ - {GOOD_PATH, EMPTY_DIR, NON_EXISTING_DIR}, - {EMPTY_DIR, NON_EXISTING_DIR, GOOD_PATH}, - {GOOD_PATH + "/a/b/c/d", GOOD_PATH}, - {String.join(File.pathSeparator, EMPTY_DIR, NON_EXISTING_DIR, - GOOD_PATH)}, - {String.join(File.pathSeparator, EMPTY_DIR, NON_EXISTING_DIR), - String.join(File.pathSeparator, EMPTY_DIR, NON_EXISTING_DIR, - GOOD_PATH)}, - {}, - {EMPTY_DIR} - }); - } - - public ModulePathTest(String... modulePathArgs) { - this.modulePathArgs = List.of(modulePathArgs); - } - - @Test - @Parameter("benvenuto.jar:com.jar.foo/com.jar.foo.Hello") - @Parameter("benvenuto.jmod:com.jmod.foo/com.jmod.foo.JModHello") - public void test(String javaAppDesc) throws IOException { - JavaAppDesc appDesc = JavaAppDesc.parse(javaAppDesc); - - Path goodModulePath = TKit.createTempDirectory("modules"); - - HelloApp.createBundle(appDesc, goodModulePath); - - JPackageCommand cmd = new JPackageCommand() - .setArgumentValue("--dest", TKit.workDir().resolve("output")) - .setDefaultAppName() - .setPackageType(PackageType.IMAGE); - - if (TKit.isWindows()) { - cmd.addArguments("--win-console"); - } - - cmd.addArguments("--module", String.join("/", appDesc.moduleName(), - appDesc.className())); - - // Ignore runtime that can be set for all tests. Usually if default - // runtime is set, it is fake one to save time on running jlink and - // copying megabytes of data from Java home to application image. - // We need proper runtime for this test. - cmd.ignoreDefaultRuntime(true); - - Path emptyDir = TKit.createTempDirectory("empty-dir"); - Path nonExistingDir = TKit.withTempDirectory("non-existing-dir", x -> {}); - - Function substitute = str -> { - String v = str; - v = v.replace(GOOD_PATH, goodModulePath.toString()); - v = v.replace(EMPTY_DIR, emptyDir.toString()); - v = v.replace(NON_EXISTING_DIR, nonExistingDir.toString()); - return v; - }; - - boolean withGoodPath = modulePathArgs.stream().anyMatch( - s -> s.contains(GOOD_PATH)); - - cmd.addArguments(modulePathArgs.stream().map(arg -> Stream.of( - "--module-path", substitute.apply(arg))).flatMap(s -> s).collect( - Collectors.toList())); - - if (withGoodPath) { - cmd.executeAndAssertHelloAppImageCreated(); - } else { - final CannedFormattedString expectedErrorMessage; - if (modulePathArgs.isEmpty()) { - expectedErrorMessage = JPackageCommand.makeError( - "ERR_MissingArgument2", "--runtime-image", "--module-path"); - } else { - expectedErrorMessage = JPackageCommand.makeError( - "error.no-module-in-path", appDesc.moduleName()); - } - - cmd.validateErr(expectedErrorMessage).execute(1); - } - } - - private final List modulePathArgs; - - private static final String GOOD_PATH = "@GoodPath@"; - private static final String EMPTY_DIR = "@EmptyDir@"; - private static final String NON_EXISTING_DIR = "@NonExistingDir@"; -} diff --git a/test/jdk/tools/jpackage/share/ModulePathTest2.java b/test/jdk/tools/jpackage/share/ModulePathTest2.java deleted file mode 100644 index b2cc674e7e9..00000000000 --- a/test/jdk/tools/jpackage/share/ModulePathTest2.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -import java.io.IOException; -import java.nio.file.Path; -import jdk.jpackage.test.HelloApp; -import jdk.jpackage.test.JavaAppDesc; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.TKit; - - -/* - * @test - * @summary jpackage with --module-path testing - * @library /test/jdk/tools/jpackage/helpers - * @build jdk.jpackage.test.* - * @compile -Xlint:all -Werror ModulePathTest2.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=ModulePathTest2 - */ - -public final class ModulePathTest2 { - - /** - * Test case for JDK-8233265. - * Adding modules in .jmod files for non-modular app results in unexpected - * jpackage failure. - * @param mainAppDesc - */ - @Test - @Parameter("Hello!") - @Parameter("com.foo/com.foo.ModuleApp") - public void test8233265(String mainAppDesc) throws IOException { - JPackageCommand cmd = JPackageCommand.helloAppImage(mainAppDesc); - - // The test should make jpackage invoke jlink. - cmd.ignoreDefaultRuntime(true); - - Path modulePath = cmd.getArgumentValue("--module-path", () -> null, Path::of); - if (modulePath == null) { - modulePath = TKit.createTempDirectory("input-modules"); - cmd.addArguments("--module-path", modulePath); - } - - JavaAppDesc extraModule = JavaAppDesc.parse("x.jmod:com.x/com.x.Y"); - HelloApp.createBundle(extraModule, modulePath); - cmd.addArguments("--add-modules", extraModule.moduleName()); - - cmd.executeAndAssertHelloAppImageCreated(); - } -} diff --git a/test/jdk/tools/jpackage/share/ModulePathTest3.java b/test/jdk/tools/jpackage/share/ModulePathTest3.java deleted file mode 100644 index c3960c0d4c8..00000000000 --- a/test/jdk/tools/jpackage/share/ModulePathTest3.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -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 javax.xml.xpath.XPathExpressionException; -import jdk.jpackage.test.AppImageFile; -import jdk.jpackage.test.HelloApp; -import jdk.jpackage.test.JavaAppDesc; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Annotations.Parameters; -import jdk.jpackage.test.Executor; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.JavaTool; -import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.TKit; - - -/* - * @test - * @summary jpackage for app's module linked in external runtime - * @library /test/jdk/tools/jpackage/helpers - * @build jdk.jpackage.test.* - * @compile -Xlint:all -Werror ModulePathTest3.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=ModulePathTest3 - */ - -public final class ModulePathTest3 { - - public ModulePathTest3(String jlinkOutputSubdir, String runtimeSubdir) { - this.jlinkOutputSubdir = Path.of(jlinkOutputSubdir); - this.runtimeSubdir = Path.of(runtimeSubdir); - } - - /** - * Test case for JDK-8248254. - * App's module in runtime directory. - */ - @Test - public void test8248254() throws XPathExpressionException, IOException { - testIt("me.mymodule/me.mymodule.Main"); - } - - private void testIt(String mainAppDesc) throws XPathExpressionException, - IOException { - final JavaAppDesc appDesc = JavaAppDesc.parse(mainAppDesc); - final Path moduleOutputDir = TKit.createTempDirectory("modules"); - HelloApp.createBundle(appDesc, moduleOutputDir); - - final Path workDir = TKit.createTempDirectory("runtime").resolve("data"); - final Path jlinkOutputDir = workDir.resolve(jlinkOutputSubdir); - Files.createDirectories(jlinkOutputDir.getParent()); - - new Executor() - .setToolProvider(JavaTool.JLINK) - .dumpOutput() - .addArguments( - "--add-modules", appDesc.moduleName(), - "--output", jlinkOutputDir.toString(), - "--module-path", moduleOutputDir.resolve(appDesc.jarFileName()).toString(), - "--strip-debug", - "--no-header-files", - "--no-man-pages", - "--strip-native-commands") - .execute(); - - JPackageCommand cmd = new JPackageCommand() - .setDefaultAppName() - .setPackageType(PackageType.IMAGE) - .setDefaultInputOutput() - .removeArgumentWithValue("--input") - .addArguments("--module", appDesc.moduleName() + "/" + appDesc.className()) - .setArgumentValue("--runtime-image", workDir.resolve(runtimeSubdir)); - - cmd.executeAndAssertHelloAppImageCreated(); - - if (appDesc.moduleVersion() != null) { - String actualVersion = AppImageFile.load(cmd.outputBundle()).version(); - TKit.assertEquals(appDesc.moduleVersion(), actualVersion, - "Check application version"); - } - } - - @Parameters - public static Collection data() { - final List paths = new ArrayList<>(); - paths.add(new String[] { "", "" }); - if (TKit.isOSX()) { - // On OSX jpackage should accept both runtime root and runtime home - // directories. - paths.add(new String[] { "Contents/Home", "" }); - } - - List data = new ArrayList<>(); - for (var pathCfg : paths) { - data.add(new Object[] { pathCfg[0], pathCfg[1] }); - } - - return data; - } - - private final Path jlinkOutputSubdir; - private final Path runtimeSubdir; -} diff --git a/test/jdk/tools/jpackage/share/NoMPathRuntimeTest.java b/test/jdk/tools/jpackage/share/NoMPathRuntimeTest.java deleted file mode 100644 index 91679945925..00000000000 --- a/test/jdk/tools/jpackage/share/NoMPathRuntimeTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -import java.io.IOException; -import java.nio.file.Files; -import java.util.Collection; -import java.util.ArrayList; -import java.util.List; -import java.nio.file.Path; -import jdk.jpackage.test.Annotations.Parameters; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Executor; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.JavaAppDesc; -import jdk.jpackage.test.JavaTool; -import jdk.jpackage.test.TKit; -import jdk.jpackage.test.HelloApp; - - -/* - * @test - * @summary test '--runtime-image' option of jpackage - * @library /test/jdk/tools/jpackage/helpers - * @build jdk.jpackage.test.* - * @compile -Xlint:all -Werror NoMPathRuntimeTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=NoMPathRuntimeTest - */ - -public final class NoMPathRuntimeTest { - - public NoMPathRuntimeTest(String jlinkOutputSubdir, String runtimeSubdir) { - this.jlinkOutputSubdir = Path.of(jlinkOutputSubdir); - this.runtimeSubdir = Path.of(runtimeSubdir); - } - - @Test - public void test() throws IOException { - JavaAppDesc appDesc = JavaAppDesc.parse("com.foo/com.foo.main.Aloha"); - - JPackageCommand cmd = JPackageCommand.helloAppImage(appDesc); - - // Build module jar. - cmd.executePrerequisiteActions(); - - final Path workDir = TKit.createTempDirectory("runtime").resolve("data"); - final Path jlinkOutputDir = workDir.resolve(jlinkOutputSubdir); - Files.createDirectories(jlinkOutputDir.getParent()); - - // List of modules required for test app. - final var modules = new String[] { - "java.base", - "java.desktop" - }; - - Executor jlink = new Executor() - .setToolProvider(JavaTool.JLINK) - .dumpOutput() - .addArguments( - "--add-modules", String.join(",", modules), - "--output", jlinkOutputDir.toString(), - "--strip-debug", - "--no-header-files", - "--no-man-pages"); - - jlink.addArguments("--add-modules", appDesc.moduleName(), - "--module-path", Path.of(cmd.getArgumentValue("--module-path")) - .resolve("hello.jar").toString()); - - jlink.execute(); - - // non-modular jar in current dir caused error whe no module-path given - cmd.removeArgumentWithValue("--module-path"); - - cmd.setArgumentValue("--runtime-image", workDir.resolve(runtimeSubdir)); - Path junkJar = null; - try { - // create a non-modular jar in the current directory - junkJar = HelloApp.createBundle( - JavaAppDesc.parse("junk.jar:Hello"), Path.of(".")); - - cmd.executeAndAssertHelloAppImageCreated(); - } finally { - if (junkJar != null) { - TKit.deleteIfExists(junkJar); - } - } - - } - - @Parameters - public static Collection data() { - - final List paths = new ArrayList<>(); - paths.add(new String[] { "", "" }); - if (TKit.isOSX()) { - // On OSX jpackage should accept both runtime root and runtime home - // directories. - paths.add(new String[] { "Contents/Home", "" }); - } - - List data = new ArrayList<>(); - for (var pathCfg : paths) { - data.add(new Object[] { pathCfg[0], pathCfg[1] }); - } - - return data; - } - - private final Path jlinkOutputSubdir; - private final Path runtimeSubdir; -} From a1b4ad097e38d5769556814df84992f2d7aae83d Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 6 Mar 2026 03:59:06 +0000 Subject: [PATCH 085/170] 8379345: jpackage: Fix issues in tests to improve their flexibility Reviewed-by: almatvee --- .../helpers/jdk/jpackage/test/MacSign.java | 81 ++++++++---- .../jdk/jpackage/test/MacSignVerify.java | 7 +- .../helpers/jdk/jpackage/test/TKit.java | 20 --- .../jdk/jpackage/internal/cli/MainTest.java | 1 + .../SigningRuntimeImagePackageTest.java | 2 +- .../jpackage/share/FileAssociationsTest.java | 12 +- .../jdk/tools/jpackage/share/LicenseTest.java | 119 ++++++++++-------- .../jpackage/windows/WinInstallerUiTest.java | 30 +++-- 8 files changed, 159 insertions(+), 113 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java index 20f7ac41eef..81e5da34140 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java @@ -67,6 +67,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; +import jdk.internal.util.OSVersion; import jdk.jpackage.internal.util.MemoizingSupplier; import jdk.jpackage.internal.util.function.ExceptionBox; import jdk.jpackage.internal.util.function.ThrowingConsumer; @@ -233,7 +234,7 @@ import jdk.jpackage.internal.util.function.ThrowingSupplier; * An untrusted certificate can NOT be used with /usr/bin/codesign. Use * *
    - * /usr/bin/security security add-trusted-cert -k foo.keychain cert.pem
    + * /usr/bin/security add-trusted-cert -k foo.keychain cert.pem
      * 
    * * command to add trusted certificate from "cert.pem" file to "foo.keychain" @@ -440,7 +441,21 @@ public final class MacSign { } Keychain unlock() { - createExecutor("unlock-keychain").execute(); + var exec = createExecutor("unlock-keychain"); + + exec.execute(); + + if (UnlockKeychainWithOsascript.VALUE) { + exec = Executor.of("osascript") + .addArguments(SIGN_UTILS_SCRIPT.toString(), "run-shell-script") + .addArgument(Stream.concat( + Stream.of(exec.getExecutable().orElseThrow().toString()), + exec.getAllArguments().stream() + ).collect(joining(" "))); + + exec.execute(); + } + return this; } @@ -576,29 +591,43 @@ public final class MacSign { } private static CertificateStats create(KeychainWithCertsSpec spec) { - final var allCertificates = spec.keychain().findCertificates(); final List allResolvedCertificateRequests = new ArrayList<>(); final Map unmappedCertificates = new HashMap<>(); - withTempDirectory(workDir -> { - for (final var cert : allCertificates) { - ResolvedCertificateRequest resolvedCertificateRequest; - try { - resolvedCertificateRequest = new ResolvedCertificateRequest(cert); - } catch (RuntimeException ex) { - unmappedCertificates.put(cert, ExceptionBox.unbox(ex)); - continue; - } + final Runnable workload = () -> { + final var allCertificates = spec.keychain().findCertificates(); + withTempDirectory(workDir -> { + for (final var cert : allCertificates) { + ResolvedCertificateRequest resolvedCertificateRequest; + try { + resolvedCertificateRequest = new ResolvedCertificateRequest(cert); + } catch (RuntimeException ex) { + unmappedCertificates.put(cert, ExceptionBox.unbox(ex)); + continue; + } - if (spec.certificateRequests().stream().anyMatch(resolvedCertificateRequest.installed()::match)) { - final var certFile = workDir.resolve(CertificateHash.of(cert).toString() + ".pem"); - final var verifyStatus = verifyCertificate(resolvedCertificateRequest, spec.keychain(), certFile); - resolvedCertificateRequest = resolvedCertificateRequest.copyVerified(verifyStatus); - } + if (spec.certificateRequests().stream().anyMatch(resolvedCertificateRequest.installed()::match)) { + final var certFile = workDir.resolve(CertificateHash.of(cert).toString() + ".pem"); + final var verifyStatus = verifyCertificate(resolvedCertificateRequest, spec.keychain(), certFile); + resolvedCertificateRequest = resolvedCertificateRequest.copyVerified(verifyStatus); + } - allResolvedCertificateRequests.add(resolvedCertificateRequest); - } - }); + allResolvedCertificateRequests.add(resolvedCertificateRequest); + } + }); + }; + + // Starting from some macOS version, it is no longer necessary to have the keychain + // in the list of keychains when running the "/usr/bin/security verify-cert ..." command to verify its certificate(s). + // The exact version when they relaxed this constraint is unknown, but it is still required on Catalina 10.15.7. + // On Catalina, if the keychain is not in the list of keychains, "/usr/bin/security verify-cert ..." command + // executed on the certificates of this keychain returns "untrusted" result. + if (OSVersion.current().compareTo(new OSVersion(10, 16)) < 0) { + // macOS Catalina or older + withKeychains(spec).addToSearchList().run(workload); + } else { + workload.run(); + } return new CertificateStats(allResolvedCertificateRequests, List.copyOf(spec.certificateRequests()), unmappedCertificates); @@ -1272,7 +1301,11 @@ public final class MacSign { for (final var quite : List.of(true, false)) { result = security("verify-cert", "-L", "-n", quite ? "-q" : "-v", - "-c", certFile.normalize().toString(), + // Use "-r" option to verify the certificate against itself. + // "-c" option works on newer macOS versions, but on older ones (at least on Catalina 10.15.7), + // in case there are two self-signed certificates with the same name in the given keychain, + // it links them in the certificate list and fails verification. + "-r", certFile.normalize().toString(), "-k", keychain.name(), "-p", resolvedCertificateRequest.installed().type().verifyPolicy()).saveOutput(!quite).executeWithoutExitCodeCheck(); if (result.getExitCode() == 0) { @@ -1463,4 +1496,10 @@ public final class MacSign { // faketime is not a standard macOS command. // One way to get it is with Homebrew. private static final Path FAKETIME = Path.of(Optional.ofNullable(TKit.getConfigProperty("faketime")).orElse("/usr/local/bin/faketime")); + + // Run the "/usr/bin/system unlock-keychain" command in Terminal.app if + // the current process runs in an SSH session and the OS version is macOS Catalina or older. + private static final class UnlockKeychainWithOsascript { + static final boolean VALUE = System.getenv("SSH_CONNECTION") != null && OSVersion.current().compareTo(new OSVersion(10, 16)) < 0; + } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java index 01c510070be..404811ea0f8 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java @@ -93,8 +93,11 @@ public final class MacSignVerify { final var exec = Executor.of( "/usr/bin/codesign", "-d", - "--entitlements", "-", - "--xml", path.toString()).saveOutput().dumpOutput().binaryOutput(); + // `--entitlements :-` will print entitlements as XML plist in the stdout and "Executable=..." message to the stderr. + // Prefer this option combination to `--entitlements - --xml` as + // the latter doesn't work on older macOS releases (Proved unsupported on Catalina 10.15.7). + "--entitlements", ":-", + path.toString()).saveOutput().dumpOutput().binaryOutput(); final var result = exec.execute(); var xml = result.byteStdout(); if (xml.length == 0) { 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 db76309c292..04b828677ca 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -37,7 +37,6 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; @@ -606,25 +605,6 @@ public final class TKit { return JtregSkippedExceptionClass.INSTANCE.isInstance(t); } - public static Path createRelativePathCopy(final Path file) { - Path fileCopy = ThrowingSupplier.toSupplier(() -> { - Path localPath = createTempFile(file.getFileName()); - Files.copy(file, localPath, StandardCopyOption.REPLACE_EXISTING); - return localPath; - }).get().toAbsolutePath().normalize(); - - final Path basePath = Path.of(".").toAbsolutePath().normalize(); - try { - return basePath.relativize(fileCopy); - } catch (IllegalArgumentException ex) { - // May happen on Windows: java.lang.IllegalArgumentException: 'other' has different root - trace(String.format("Failed to relativize [%s] at [%s]", fileCopy, - basePath)); - printStackTrace(ex); - } - return file; - } - public static void waitForFileCreated(Path fileToWaitFor, Duration timeout, Duration afterCreatedTimeout) throws IOException { waitForFileCreated(fileToWaitFor, timeout); diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java index 3f933093e97..1b89d23c301 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/MainTest.java @@ -154,6 +154,7 @@ public class MainTest extends JUnitAdapter { JPackageCommand.helloAppImage() .ignoreDefaultVerbose(true) + .ignoreDefaultRuntime(true) .useToolProvider(jpackageToolProviderMock) .execute(jpackageExitCode); } diff --git a/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java b/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java index 54021aa2a0b..11b466ed715 100644 --- a/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java @@ -200,7 +200,7 @@ public class SigningRuntimeImagePackageTest { // This way we can test if jpackage keeps or replaces the signature of // the predefined runtime bundle when backing it in the pkg or dmg installer. return new SignKeyOptionWithKeychain( - SignKeyOption.Type.SIGN_KEY_USER_SHORT_NAME, + SignKeyOption.Type.SIGN_KEY_IDENTITY_APP_IMAGE, SigningBase.StandardCertificateRequest.CODESIGN_ACME_TECH_LTD, SigningBase.StandardKeychain.MAIN.keychain()); } diff --git a/test/jdk/tools/jpackage/share/FileAssociationsTest.java b/test/jdk/tools/jpackage/share/FileAssociationsTest.java index c9bd690d73f..0af7e7a54ff 100644 --- a/test/jdk/tools/jpackage/share/FileAssociationsTest.java +++ b/test/jdk/tools/jpackage/share/FileAssociationsTest.java @@ -23,6 +23,8 @@ import static java.util.Map.entry; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import jdk.jpackage.test.Annotations.Parameter; @@ -84,7 +86,7 @@ public class FileAssociationsTest { @Test @Parameter("true") @Parameter("false") - public static void test(boolean includeDescription) { + public static void test(boolean includeDescription) throws IOException { PackageTest packageTest = new PackageTest(); // Not supported @@ -96,10 +98,8 @@ public class FileAssociationsTest { } fa.applyTo(packageTest); - Path icon = TKit.TEST_SRC_ROOT.resolve(Path.of("resources", "icon" - + TKit.ICON_SUFFIX)); - - icon = TKit.createRelativePathCopy(icon); + var icon = TKit.createTempDirectory("icon-dir").resolve(ICON.getFileName()); + Files.copy(ICON, icon); new FileAssociations("jptest2") .setFilename("fa2") @@ -151,4 +151,6 @@ public class FileAssociationsTest { .addInitializer(JPackageCommand::setFakeRuntime) .setExpectedExitCode(1); } + + private static final Path ICON = TKit.TEST_SRC_ROOT.resolve(Path.of("resources", "icon" + TKit.ICON_SUFFIX)); } diff --git a/test/jdk/tools/jpackage/share/LicenseTest.java b/test/jdk/tools/jpackage/share/LicenseTest.java index 9c2d1077584..bf4c26fe76a 100644 --- a/test/jdk/tools/jpackage/share/LicenseTest.java +++ b/test/jdk/tools/jpackage/share/LicenseTest.java @@ -21,21 +21,23 @@ * questions. */ +import static jdk.internal.util.OperatingSystem.LINUX; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; -import static jdk.internal.util.OperatingSystem.LINUX; +import jdk.jpackage.internal.util.Slot; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.LinuxHelper; import jdk.jpackage.test.Executor; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.LinuxHelper; +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.PackageType; import jdk.jpackage.test.TKit; /** @@ -93,11 +95,7 @@ public class LicenseTest { @Test public static void testCommon() { - PackageTest test = new PackageTest().configureHelloApp() - .addInitializer(cmd -> { - cmd.addArguments("--license-file", TKit.createRelativePathCopy( - LICENSE_FILE)); - }); + PackageTest test = new PackageTest().configureHelloApp().mutate(LicenseTest::setLicenseFile); initMacDmgLicenseVerifier(test.forTypes(PackageType.MAC_DMG)); initLinuxLicenseVerifier(test.forTypes(PackageType.LINUX)); @@ -127,19 +125,16 @@ public class LicenseTest { @Test(ifOS = LINUX) public static void testCustomDebianCopyright() { - new CustomDebianCopyrightTest().run(); + new CustomDebianCopyrightTest(false).run(); } @Test(ifOS = LINUX) public static void testCustomDebianCopyrightSubst() { - new CustomDebianCopyrightTest().withSubstitution(true).run(); + new CustomDebianCopyrightTest(true).run(); } private static PackageTest initMacDmgLicenseVerifier(PackageTest test) { - return test - .addBundleVerifier(cmd -> { - verifyLicenseFileInDMGPackage(cmd); - }); + return test.addBundleVerifier(LicenseTest::verifyLicenseFileInDMGPackage); } private static void verifyLicenseFileInDMGPackage(JPackageCommand cmd) @@ -179,10 +174,9 @@ public class LicenseTest { PackageTest test = new PackageTest() .forTypes(PackageType.LINUX) .configureHelloApp() + .addInitializer(JPackageCommand::setFakeRuntime) + .mutate(LicenseTest::setLicenseFile) .addInitializer(cmd -> { - cmd.setFakeRuntime(); - cmd.addArguments("--license-file", TKit.createRelativePathCopy( - LICENSE_FILE)); cmd.addArguments("--install-dir", installDir); }); @@ -191,6 +185,18 @@ public class LicenseTest { test.run(); } + private static void setLicenseFile(PackageTest test) { + var inputLicenseFile = Slot.createEmpty(); + + test.addRunOnceInitializer(() -> { + var dir = TKit.createTempDirectory("license-dir"); + inputLicenseFile.set(dir.resolve(LICENSE_FILE.getFileName())); + Files.copy(LICENSE_FILE, inputLicenseFile.get()); + }).addInitializer(cmd -> { + cmd.setArgumentValue("--license-file", inputLicenseFile.get()); + }); + } + private static Path rpmLicenseFile(JPackageCommand cmd) { final Path licenseRoot = Path.of( new Executor() @@ -296,12 +302,36 @@ public class LicenseTest { TKit.assertPathExists(licenseFile.getParent(), false); } - private static class CustomDebianCopyrightTest { - CustomDebianCopyrightTest() { - withSubstitution(false); + private record CustomDebianCopyrightTest(boolean withSubstitution) { + + private String copyright() { + // Different values just to make easy to figure out from the test log which test was executed. + if (withSubstitution) { + return "Duke (C)"; + } else { + return "Java (C)"; + } } - private List licenseFileText(String copyright, String licenseText) { + private String licenseText() { + // Different values just to make easy to figure out from the test log which test was executed. + if (withSubstitution) { + return "The quick brown fox\n jumps over the lazy dog"; + } else { + return "How vexingly quick daft zebras jump!"; + } + } + + private String name() { + // Different values just to make easy to figure out from the test log which test was executed. + if (withSubstitution) { + return "CustomDebianCopyrightWithSubst"; + } else { + return "CustomDebianCopyright"; + } + } + + static private List licenseFileText(String copyright, String licenseText) { List lines = new ArrayList<>(List.of( String.format("Copyright=%s", copyright), "Foo", @@ -313,28 +343,14 @@ public class LicenseTest { private List licenseFileText() { if (withSubstitution) { - return licenseFileText("APPLICATION_COPYRIGHT", - "APPLICATION_LICENSE_TEXT"); + return licenseFileText("APPLICATION_COPYRIGHT", "APPLICATION_LICENSE_TEXT"); } else { return expectedLicenseFileText(); } } private List expectedLicenseFileText() { - return licenseFileText(copyright, licenseText); - } - - CustomDebianCopyrightTest withSubstitution(boolean v) { - withSubstitution = v; - // Different values just to make easy to figure out from the test log which test was executed. - if (v) { - copyright = "Duke (C)"; - licenseText = "The quick brown fox\n jumps over the lazy dog"; - } else { - copyright = "Java (C)"; - licenseText = "How vexingly quick daft zebras jump!"; - } - return this; + return licenseFileText(copyright(), licenseText()); } void run() { @@ -343,20 +359,19 @@ public class LicenseTest { .addInitializer(cmd -> { // Create source license file. Files.write(srcLicenseFile, List.of( - licenseText.split("\\R", -1))); + licenseText().split("\\R", -1))); cmd.setFakeRuntime(); - cmd.setArgumentValue("--name", String.format("%s%s", - withSubstitution ? "CustomDebianCopyrightWithSubst" : "CustomDebianCopyright", - cmd.name())); + cmd.setArgumentValue("--name", String.format("%s%s", name(), cmd.name())); cmd.addArguments("--license-file", srcLicenseFile); - cmd.addArguments("--copyright", copyright); - cmd.addArguments("--resource-dir", RESOURCE_DIR); + cmd.addArguments("--copyright", copyright()); + + var resourceDir = TKit.createTempDirectory("resources"); + + cmd.addArguments("--resource-dir", resourceDir); // Create copyright template file in a resource dir. - Files.createDirectories(RESOURCE_DIR); - Files.write(RESOURCE_DIR.resolve("copyright"), - licenseFileText()); + Files.write(resourceDir.resolve("copyright"), licenseFileText()); }) .addInstallVerifier(cmd -> { Path installedLicenseFile = linuxLicenseFile(cmd); @@ -368,12 +383,6 @@ public class LicenseTest { }) .run(); } - - private boolean withSubstitution; - private String copyright; - private String licenseText; - - private final Path RESOURCE_DIR = TKit.workDir().resolve("resources"); } private static final Path LICENSE_FILE = TKit.TEST_SRC_ROOT.resolve( diff --git a/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java b/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java index 7dcf025a506..d6cebde6444 100644 --- a/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java +++ b/test/jdk/tools/jpackage/windows/WinInstallerUiTest.java @@ -21,13 +21,15 @@ * questions. */ +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.Annotations.Parameters; import java.util.List; +import jdk.jpackage.internal.util.Slot; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; import jdk.jpackage.test.TKit; @@ -108,11 +110,7 @@ public class WinInstallerUiTest { } if (withLicense) { - test.addInitializer(cmd -> { - cmd.addArguments("--license-file", TKit.createRelativePathCopy( - TKit.TEST_SRC_ROOT.resolve(Path.of("resources", - "license.txt")))); - }); + setLicenseFile(test); } test.run(); @@ -133,7 +131,21 @@ public class WinInstallerUiTest { cmd.setArgumentValue("--name", sb.toString()); } + private static void setLicenseFile(PackageTest test) { + var inputLicenseFile = Slot.createEmpty(); + + test.addRunOnceInitializer(() -> { + var dir = TKit.createTempDirectory("license-dir"); + inputLicenseFile.set(dir.resolve(LICENSE_FILE.getFileName())); + Files.copy(LICENSE_FILE, inputLicenseFile.get()); + }).addInitializer(cmd -> { + cmd.setArgumentValue("--license-file", inputLicenseFile.get()); + }); + } + private final boolean withDirChooser; private final boolean withLicense; private final boolean withShortcutPrompt; + + private static final Path LICENSE_FILE = TKit.TEST_SRC_ROOT.resolve(Path.of("resources", "license.txt")); } From e6406641d78219f29d24de32ce3c7e6781dc283f Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 6 Mar 2026 04:37:05 +0000 Subject: [PATCH 086/170] 8378758: [VectorAPI] Add Jtreg scalar operation wrappers for math operators and APIs Reviewed-by: sherman --- .../incubator/vector/ByteVector128Tests.java | 279 ++++++----- .../incubator/vector/ByteVector256Tests.java | 279 ++++++----- .../incubator/vector/ByteVector512Tests.java | 279 ++++++----- .../incubator/vector/ByteVector64Tests.java | 279 ++++++----- .../incubator/vector/ByteVectorMaxTests.java | 279 ++++++----- .../vector/DoubleVector128Tests.java | 450 +++++++++++++----- .../vector/DoubleVector256Tests.java | 450 +++++++++++++----- .../vector/DoubleVector512Tests.java | 450 +++++++++++++----- .../incubator/vector/DoubleVector64Tests.java | 450 +++++++++++++----- .../vector/DoubleVectorMaxTests.java | 450 +++++++++++++----- .../incubator/vector/FloatVector128Tests.java | 450 +++++++++++++----- .../incubator/vector/FloatVector256Tests.java | 450 +++++++++++++----- .../incubator/vector/FloatVector512Tests.java | 450 +++++++++++++----- .../incubator/vector/FloatVector64Tests.java | 450 +++++++++++++----- .../incubator/vector/FloatVectorMaxTests.java | 450 +++++++++++++----- .../incubator/vector/IntVector128Tests.java | 279 ++++++----- .../incubator/vector/IntVector256Tests.java | 279 ++++++----- .../incubator/vector/IntVector512Tests.java | 279 ++++++----- .../incubator/vector/IntVector64Tests.java | 279 ++++++----- .../incubator/vector/IntVectorMaxTests.java | 279 ++++++----- .../incubator/vector/LongVector128Tests.java | 252 ++++++---- .../incubator/vector/LongVector256Tests.java | 252 ++++++---- .../incubator/vector/LongVector512Tests.java | 252 ++++++---- .../incubator/vector/LongVector64Tests.java | 252 ++++++---- .../incubator/vector/LongVectorMaxTests.java | 252 ++++++---- .../incubator/vector/ShortVector128Tests.java | 279 ++++++----- .../incubator/vector/ShortVector256Tests.java | 279 ++++++----- .../incubator/vector/ShortVector512Tests.java | 279 ++++++----- .../incubator/vector/ShortVector64Tests.java | 279 ++++++----- .../incubator/vector/ShortVectorMaxTests.java | 279 ++++++----- test/jdk/jdk/incubator/vector/gen-template.sh | 103 ++-- .../Kernel-Reduction-Masked-op.template | 2 +- .../templates/Kernel-Reduction-op.template | 2 +- .../templates/Unit-Binary-op-math.template | 2 +- .../templates/Unit-Compare-Broadcast.template | 8 +- .../templates/Unit-Miscellaneous.template | 23 +- .../Unit-Reduction-Scalar-Masked-op.template | 4 +- .../Unit-Reduction-Scalar-op.template | 4 +- .../templates/Unit-Reduction-op.template | 10 +- .../templates/Unit-Unary-op-math.template | 2 +- .../vector/templates/Unit-header.template | 220 ++++++++- 41 files changed, 6779 insertions(+), 3546 deletions(-) diff --git a/test/jdk/jdk/incubator/vector/ByteVector128Tests.java b/test/jdk/jdk/incubator/vector/ByteVector128Tests.java index 91148fd5d66..ca6fa537ac4 100644 --- a/test/jdk/jdk/incubator/vector/ByteVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/ByteVector128Tests.java @@ -1574,6 +1574,59 @@ public class ByteVector128Tests extends AbstractVectorTest { return a >= b; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + + static byte scalar_or(byte a, byte b) { + return (byte)(a | b); + } + + static byte scalar_and(byte a, byte b) { + return (byte)(a & b); + } + + static byte scalar_xor(byte a, byte b) { + return (byte)(a ^ b); + } + + static byte scalar_add(byte a, byte b) { + return (byte)(a + b); + } + + static byte scalar_sub(byte a, byte b) { + return (byte)(a - b); + } + + static byte scalar_mul(byte a, byte b) { + return (byte)(a * b); + } + + static byte scalar_min(byte a, byte b) { + return (byte)(Math.min(a, b)); + } + + static byte scalar_max(byte a, byte b) { + return (byte)(Math.max(a, b)); + } + + static byte scalar_div(byte a, byte b) { + return (byte)(a / b); + } + + static byte scalar_fma(byte a, byte b, byte c) { + return (byte)(Math.fma(a, b, c)); + } + + static byte scalar_abs(byte a) { + return (byte)(Math.abs(a)); + } + + static byte scalar_neg(byte a) { + return ((byte)-a); + } + + static boolean ult(byte a, byte b) { return Byte.compareUnsigned(a, b) < 0; } @@ -1590,9 +1643,6 @@ public class ByteVector128Tests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } - static byte firstNonZero(byte a, byte b) { - return Byte.compare(a, (byte) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1701,7 +1751,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte ADD(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1722,7 +1772,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte add(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1779,7 +1829,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte SUB(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1800,7 +1850,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte sub(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1857,7 +1907,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte MUL(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1878,7 +1928,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte mul(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -2025,7 +2075,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte FIRST_NONZERO(byte a, byte b) { - return (byte)((a)!=0?a:b); + return (byte)(firstNonZero(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3239,7 +3289,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte MIN(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3260,7 +3310,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte min(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3279,7 +3329,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte MAX(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3300,7 +3350,7 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte max(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3668,7 +3718,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ANDReduce(byte[] a, int idx) { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3677,7 +3727,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ANDReduceAll(byte[] a) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3695,7 +3745,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3708,20 +3758,20 @@ public class ByteVector128Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = AND_IDENTITY; - assertEquals((byte) (id & id), id, + assertEquals((byte) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id & x), x); - assertEquals((byte) (x & id), x); + assertEquals((byte) (scalar_and(id, x)), x); + assertEquals((byte) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id & x), x, + assertEquals((byte) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x & id), x, + assertEquals((byte) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3730,7 +3780,7 @@ public class ByteVector128Tests extends AbstractVectorTest { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3739,7 +3789,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ANDReduceAllMasked(byte[] a, boolean[] mask) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3759,7 +3809,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3770,7 +3820,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ORReduce(byte[] a, int idx) { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3779,7 +3829,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ORReduceAll(byte[] a) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3797,7 +3847,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3810,20 +3860,20 @@ public class ByteVector128Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = OR_IDENTITY; - assertEquals((byte) (id | id), id, + assertEquals((byte) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id | x), x); - assertEquals((byte) (x | id), x); + assertEquals((byte) (scalar_or(id, x)), x); + assertEquals((byte) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id | x), x, + assertEquals((byte) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x | id), x, + assertEquals((byte) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3832,7 +3882,7 @@ public class ByteVector128Tests extends AbstractVectorTest { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3841,7 +3891,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ORReduceAllMasked(byte[] a, boolean[] mask) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3861,7 +3911,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3872,7 +3922,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte XORReduce(byte[] a, int idx) { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3881,7 +3931,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte XORReduceAll(byte[] a) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3899,7 +3949,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3912,20 +3962,20 @@ public class ByteVector128Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = XOR_IDENTITY; - assertEquals((byte) (id ^ id), id, + assertEquals((byte) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id ^ x), x); - assertEquals((byte) (x ^ id), x); + assertEquals((byte) (scalar_xor(id, x)), x); + assertEquals((byte) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id ^ x), x, + assertEquals((byte) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x ^ id), x, + assertEquals((byte) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3934,7 +3984,7 @@ public class ByteVector128Tests extends AbstractVectorTest { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3943,7 +3993,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte XORReduceAllMasked(byte[] a, boolean[] mask) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3963,7 +4013,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3974,7 +4024,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ADDReduce(byte[] a, int idx) { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3983,7 +4033,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ADDReduceAll(byte[] a) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4001,7 +4051,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4014,20 +4064,20 @@ public class ByteVector128Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = ADD_IDENTITY; - assertEquals((byte) (id + id), id, + assertEquals((byte) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id + x), x); - assertEquals((byte) (x + id), x); + assertEquals((byte) (scalar_add(id, x)), x); + assertEquals((byte) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id + x), x, + assertEquals((byte) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x + id), x, + assertEquals((byte) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4036,7 +4086,7 @@ public class ByteVector128Tests extends AbstractVectorTest { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4045,7 +4095,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte ADDReduceAllMasked(byte[] a, boolean[] mask) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4065,7 +4115,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4076,7 +4126,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MULReduce(byte[] a, int idx) { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4085,7 +4135,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MULReduceAll(byte[] a) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4103,7 +4153,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4116,20 +4166,20 @@ public class ByteVector128Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MUL_IDENTITY; - assertEquals((byte) (id * id), id, + assertEquals((byte) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id * x), x); - assertEquals((byte) (x * id), x); + assertEquals((byte) (scalar_mul(id, x)), x); + assertEquals((byte) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id * x), x, + assertEquals((byte) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x * id), x, + assertEquals((byte) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4138,7 +4188,7 @@ public class ByteVector128Tests extends AbstractVectorTest { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4147,7 +4197,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MULReduceAllMasked(byte[] a, boolean[] mask) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4167,7 +4217,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4178,7 +4228,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4187,7 +4237,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4205,7 +4255,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4218,20 +4268,20 @@ public class ByteVector128Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MIN_IDENTITY; - assertEquals((byte) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.min(id, x), x); - assertEquals((byte) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4240,7 +4290,7 @@ public class ByteVector128Tests extends AbstractVectorTest { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4249,7 +4299,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4269,7 +4319,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4280,7 +4330,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4289,7 +4339,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4307,7 +4357,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4320,20 +4370,20 @@ public class ByteVector128Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MAX_IDENTITY; - assertEquals((byte) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.max(id, x), x); - assertEquals((byte) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4342,7 +4392,7 @@ public class ByteVector128Tests extends AbstractVectorTest { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4351,7 +4401,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4371,7 +4421,7 @@ public class ByteVector128Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5404,7 +5454,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5424,7 +5474,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5440,7 +5490,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (byte)((long)b[i]))); } } } @@ -5460,7 +5510,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (byte)((long)b[i])))); } } } @@ -5476,7 +5526,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5496,7 +5546,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5512,7 +5562,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (byte)((long)b[i]))); } } } @@ -5532,7 +5582,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (byte)((long)b[i])))); } } } @@ -6244,11 +6294,11 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte NEG(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } static byte neg(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6300,11 +6350,11 @@ public class ByteVector128Tests extends AbstractVectorTest { } static byte ABS(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } static byte abs(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6795,7 +6845,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6811,7 +6861,7 @@ public class ByteVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6891,7 +6941,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static long ADDReduceLong(byte[] a, int idx) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6900,7 +6950,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static long ADDReduceAllLong(byte[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((byte)res, (byte)ADDReduceLong(a, i)); } return res; @@ -6918,8 +6968,8 @@ public class ByteVector128Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6929,8 +6979,9 @@ public class ByteVector128Tests extends AbstractVectorTest { static long ADDReduceLongMasked(byte[] a, int idx, boolean[] mask) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6939,7 +6990,7 @@ public class ByteVector128Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(byte[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((byte)res, (byte)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6959,8 +7010,8 @@ public class ByteVector128Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ByteVector256Tests.java b/test/jdk/jdk/incubator/vector/ByteVector256Tests.java index 1173a4b7783..5c32d4a7f74 100644 --- a/test/jdk/jdk/incubator/vector/ByteVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/ByteVector256Tests.java @@ -1574,6 +1574,59 @@ public class ByteVector256Tests extends AbstractVectorTest { return a >= b; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + + static byte scalar_or(byte a, byte b) { + return (byte)(a | b); + } + + static byte scalar_and(byte a, byte b) { + return (byte)(a & b); + } + + static byte scalar_xor(byte a, byte b) { + return (byte)(a ^ b); + } + + static byte scalar_add(byte a, byte b) { + return (byte)(a + b); + } + + static byte scalar_sub(byte a, byte b) { + return (byte)(a - b); + } + + static byte scalar_mul(byte a, byte b) { + return (byte)(a * b); + } + + static byte scalar_min(byte a, byte b) { + return (byte)(Math.min(a, b)); + } + + static byte scalar_max(byte a, byte b) { + return (byte)(Math.max(a, b)); + } + + static byte scalar_div(byte a, byte b) { + return (byte)(a / b); + } + + static byte scalar_fma(byte a, byte b, byte c) { + return (byte)(Math.fma(a, b, c)); + } + + static byte scalar_abs(byte a) { + return (byte)(Math.abs(a)); + } + + static byte scalar_neg(byte a) { + return ((byte)-a); + } + + static boolean ult(byte a, byte b) { return Byte.compareUnsigned(a, b) < 0; } @@ -1590,9 +1643,6 @@ public class ByteVector256Tests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } - static byte firstNonZero(byte a, byte b) { - return Byte.compare(a, (byte) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1701,7 +1751,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte ADD(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1722,7 +1772,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte add(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1779,7 +1829,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte SUB(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1800,7 +1850,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte sub(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1857,7 +1907,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte MUL(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1878,7 +1928,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte mul(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -2025,7 +2075,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte FIRST_NONZERO(byte a, byte b) { - return (byte)((a)!=0?a:b); + return (byte)(firstNonZero(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3239,7 +3289,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte MIN(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3260,7 +3310,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte min(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3279,7 +3329,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte MAX(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3300,7 +3350,7 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte max(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3668,7 +3718,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ANDReduce(byte[] a, int idx) { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3677,7 +3727,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ANDReduceAll(byte[] a) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3695,7 +3745,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3708,20 +3758,20 @@ public class ByteVector256Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = AND_IDENTITY; - assertEquals((byte) (id & id), id, + assertEquals((byte) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id & x), x); - assertEquals((byte) (x & id), x); + assertEquals((byte) (scalar_and(id, x)), x); + assertEquals((byte) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id & x), x, + assertEquals((byte) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x & id), x, + assertEquals((byte) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3730,7 +3780,7 @@ public class ByteVector256Tests extends AbstractVectorTest { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3739,7 +3789,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ANDReduceAllMasked(byte[] a, boolean[] mask) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3759,7 +3809,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3770,7 +3820,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ORReduce(byte[] a, int idx) { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3779,7 +3829,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ORReduceAll(byte[] a) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3797,7 +3847,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3810,20 +3860,20 @@ public class ByteVector256Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = OR_IDENTITY; - assertEquals((byte) (id | id), id, + assertEquals((byte) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id | x), x); - assertEquals((byte) (x | id), x); + assertEquals((byte) (scalar_or(id, x)), x); + assertEquals((byte) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id | x), x, + assertEquals((byte) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x | id), x, + assertEquals((byte) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3832,7 +3882,7 @@ public class ByteVector256Tests extends AbstractVectorTest { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3841,7 +3891,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ORReduceAllMasked(byte[] a, boolean[] mask) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3861,7 +3911,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3872,7 +3922,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte XORReduce(byte[] a, int idx) { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3881,7 +3931,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte XORReduceAll(byte[] a) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3899,7 +3949,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3912,20 +3962,20 @@ public class ByteVector256Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = XOR_IDENTITY; - assertEquals((byte) (id ^ id), id, + assertEquals((byte) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id ^ x), x); - assertEquals((byte) (x ^ id), x); + assertEquals((byte) (scalar_xor(id, x)), x); + assertEquals((byte) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id ^ x), x, + assertEquals((byte) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x ^ id), x, + assertEquals((byte) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3934,7 +3984,7 @@ public class ByteVector256Tests extends AbstractVectorTest { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3943,7 +3993,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte XORReduceAllMasked(byte[] a, boolean[] mask) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3963,7 +4013,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3974,7 +4024,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ADDReduce(byte[] a, int idx) { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3983,7 +4033,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ADDReduceAll(byte[] a) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4001,7 +4051,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4014,20 +4064,20 @@ public class ByteVector256Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = ADD_IDENTITY; - assertEquals((byte) (id + id), id, + assertEquals((byte) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id + x), x); - assertEquals((byte) (x + id), x); + assertEquals((byte) (scalar_add(id, x)), x); + assertEquals((byte) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id + x), x, + assertEquals((byte) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x + id), x, + assertEquals((byte) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4036,7 +4086,7 @@ public class ByteVector256Tests extends AbstractVectorTest { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4045,7 +4095,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte ADDReduceAllMasked(byte[] a, boolean[] mask) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4065,7 +4115,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4076,7 +4126,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MULReduce(byte[] a, int idx) { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4085,7 +4135,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MULReduceAll(byte[] a) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4103,7 +4153,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4116,20 +4166,20 @@ public class ByteVector256Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MUL_IDENTITY; - assertEquals((byte) (id * id), id, + assertEquals((byte) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id * x), x); - assertEquals((byte) (x * id), x); + assertEquals((byte) (scalar_mul(id, x)), x); + assertEquals((byte) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id * x), x, + assertEquals((byte) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x * id), x, + assertEquals((byte) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4138,7 +4188,7 @@ public class ByteVector256Tests extends AbstractVectorTest { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4147,7 +4197,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MULReduceAllMasked(byte[] a, boolean[] mask) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4167,7 +4217,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4178,7 +4228,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4187,7 +4237,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4205,7 +4255,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4218,20 +4268,20 @@ public class ByteVector256Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MIN_IDENTITY; - assertEquals((byte) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.min(id, x), x); - assertEquals((byte) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4240,7 +4290,7 @@ public class ByteVector256Tests extends AbstractVectorTest { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4249,7 +4299,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4269,7 +4319,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4280,7 +4330,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4289,7 +4339,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4307,7 +4357,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4320,20 +4370,20 @@ public class ByteVector256Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MAX_IDENTITY; - assertEquals((byte) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.max(id, x), x); - assertEquals((byte) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4342,7 +4392,7 @@ public class ByteVector256Tests extends AbstractVectorTest { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4351,7 +4401,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4371,7 +4421,7 @@ public class ByteVector256Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5404,7 +5454,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5424,7 +5474,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5440,7 +5490,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (byte)((long)b[i]))); } } } @@ -5460,7 +5510,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (byte)((long)b[i])))); } } } @@ -5476,7 +5526,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5496,7 +5546,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5512,7 +5562,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (byte)((long)b[i]))); } } } @@ -5532,7 +5582,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (byte)((long)b[i])))); } } } @@ -6244,11 +6294,11 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte NEG(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } static byte neg(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6300,11 +6350,11 @@ public class ByteVector256Tests extends AbstractVectorTest { } static byte ABS(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } static byte abs(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6795,7 +6845,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6811,7 +6861,7 @@ public class ByteVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6891,7 +6941,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static long ADDReduceLong(byte[] a, int idx) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6900,7 +6950,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static long ADDReduceAllLong(byte[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((byte)res, (byte)ADDReduceLong(a, i)); } return res; @@ -6918,8 +6968,8 @@ public class ByteVector256Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6929,8 +6979,9 @@ public class ByteVector256Tests extends AbstractVectorTest { static long ADDReduceLongMasked(byte[] a, int idx, boolean[] mask) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6939,7 +6990,7 @@ public class ByteVector256Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(byte[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((byte)res, (byte)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6959,8 +7010,8 @@ public class ByteVector256Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ByteVector512Tests.java b/test/jdk/jdk/incubator/vector/ByteVector512Tests.java index 02da1889dc8..094f3bbebdc 100644 --- a/test/jdk/jdk/incubator/vector/ByteVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/ByteVector512Tests.java @@ -1574,6 +1574,59 @@ public class ByteVector512Tests extends AbstractVectorTest { return a >= b; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + + static byte scalar_or(byte a, byte b) { + return (byte)(a | b); + } + + static byte scalar_and(byte a, byte b) { + return (byte)(a & b); + } + + static byte scalar_xor(byte a, byte b) { + return (byte)(a ^ b); + } + + static byte scalar_add(byte a, byte b) { + return (byte)(a + b); + } + + static byte scalar_sub(byte a, byte b) { + return (byte)(a - b); + } + + static byte scalar_mul(byte a, byte b) { + return (byte)(a * b); + } + + static byte scalar_min(byte a, byte b) { + return (byte)(Math.min(a, b)); + } + + static byte scalar_max(byte a, byte b) { + return (byte)(Math.max(a, b)); + } + + static byte scalar_div(byte a, byte b) { + return (byte)(a / b); + } + + static byte scalar_fma(byte a, byte b, byte c) { + return (byte)(Math.fma(a, b, c)); + } + + static byte scalar_abs(byte a) { + return (byte)(Math.abs(a)); + } + + static byte scalar_neg(byte a) { + return ((byte)-a); + } + + static boolean ult(byte a, byte b) { return Byte.compareUnsigned(a, b) < 0; } @@ -1590,9 +1643,6 @@ public class ByteVector512Tests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } - static byte firstNonZero(byte a, byte b) { - return Byte.compare(a, (byte) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1701,7 +1751,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte ADD(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1722,7 +1772,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte add(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1779,7 +1829,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte SUB(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1800,7 +1850,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte sub(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1857,7 +1907,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte MUL(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1878,7 +1928,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte mul(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -2025,7 +2075,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte FIRST_NONZERO(byte a, byte b) { - return (byte)((a)!=0?a:b); + return (byte)(firstNonZero(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3239,7 +3289,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte MIN(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3260,7 +3310,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte min(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3279,7 +3329,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte MAX(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3300,7 +3350,7 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte max(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3668,7 +3718,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ANDReduce(byte[] a, int idx) { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3677,7 +3727,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ANDReduceAll(byte[] a) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3695,7 +3745,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3708,20 +3758,20 @@ public class ByteVector512Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = AND_IDENTITY; - assertEquals((byte) (id & id), id, + assertEquals((byte) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id & x), x); - assertEquals((byte) (x & id), x); + assertEquals((byte) (scalar_and(id, x)), x); + assertEquals((byte) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id & x), x, + assertEquals((byte) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x & id), x, + assertEquals((byte) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3730,7 +3780,7 @@ public class ByteVector512Tests extends AbstractVectorTest { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3739,7 +3789,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ANDReduceAllMasked(byte[] a, boolean[] mask) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3759,7 +3809,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3770,7 +3820,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ORReduce(byte[] a, int idx) { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3779,7 +3829,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ORReduceAll(byte[] a) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3797,7 +3847,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3810,20 +3860,20 @@ public class ByteVector512Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = OR_IDENTITY; - assertEquals((byte) (id | id), id, + assertEquals((byte) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id | x), x); - assertEquals((byte) (x | id), x); + assertEquals((byte) (scalar_or(id, x)), x); + assertEquals((byte) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id | x), x, + assertEquals((byte) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x | id), x, + assertEquals((byte) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3832,7 +3882,7 @@ public class ByteVector512Tests extends AbstractVectorTest { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3841,7 +3891,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ORReduceAllMasked(byte[] a, boolean[] mask) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3861,7 +3911,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3872,7 +3922,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte XORReduce(byte[] a, int idx) { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3881,7 +3931,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte XORReduceAll(byte[] a) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3899,7 +3949,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3912,20 +3962,20 @@ public class ByteVector512Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = XOR_IDENTITY; - assertEquals((byte) (id ^ id), id, + assertEquals((byte) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id ^ x), x); - assertEquals((byte) (x ^ id), x); + assertEquals((byte) (scalar_xor(id, x)), x); + assertEquals((byte) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id ^ x), x, + assertEquals((byte) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x ^ id), x, + assertEquals((byte) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3934,7 +3984,7 @@ public class ByteVector512Tests extends AbstractVectorTest { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3943,7 +3993,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte XORReduceAllMasked(byte[] a, boolean[] mask) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3963,7 +4013,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3974,7 +4024,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ADDReduce(byte[] a, int idx) { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3983,7 +4033,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ADDReduceAll(byte[] a) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4001,7 +4051,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4014,20 +4064,20 @@ public class ByteVector512Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = ADD_IDENTITY; - assertEquals((byte) (id + id), id, + assertEquals((byte) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id + x), x); - assertEquals((byte) (x + id), x); + assertEquals((byte) (scalar_add(id, x)), x); + assertEquals((byte) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id + x), x, + assertEquals((byte) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x + id), x, + assertEquals((byte) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4036,7 +4086,7 @@ public class ByteVector512Tests extends AbstractVectorTest { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4045,7 +4095,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte ADDReduceAllMasked(byte[] a, boolean[] mask) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4065,7 +4115,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4076,7 +4126,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MULReduce(byte[] a, int idx) { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4085,7 +4135,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MULReduceAll(byte[] a) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4103,7 +4153,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4116,20 +4166,20 @@ public class ByteVector512Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MUL_IDENTITY; - assertEquals((byte) (id * id), id, + assertEquals((byte) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id * x), x); - assertEquals((byte) (x * id), x); + assertEquals((byte) (scalar_mul(id, x)), x); + assertEquals((byte) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id * x), x, + assertEquals((byte) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x * id), x, + assertEquals((byte) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4138,7 +4188,7 @@ public class ByteVector512Tests extends AbstractVectorTest { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4147,7 +4197,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MULReduceAllMasked(byte[] a, boolean[] mask) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4167,7 +4217,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4178,7 +4228,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4187,7 +4237,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4205,7 +4255,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4218,20 +4268,20 @@ public class ByteVector512Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MIN_IDENTITY; - assertEquals((byte) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.min(id, x), x); - assertEquals((byte) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4240,7 +4290,7 @@ public class ByteVector512Tests extends AbstractVectorTest { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4249,7 +4299,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4269,7 +4319,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4280,7 +4330,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4289,7 +4339,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4307,7 +4357,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4320,20 +4370,20 @@ public class ByteVector512Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MAX_IDENTITY; - assertEquals((byte) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.max(id, x), x); - assertEquals((byte) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4342,7 +4392,7 @@ public class ByteVector512Tests extends AbstractVectorTest { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4351,7 +4401,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4371,7 +4421,7 @@ public class ByteVector512Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5404,7 +5454,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5424,7 +5474,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5440,7 +5490,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (byte)((long)b[i]))); } } } @@ -5460,7 +5510,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (byte)((long)b[i])))); } } } @@ -5476,7 +5526,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5496,7 +5546,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5512,7 +5562,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (byte)((long)b[i]))); } } } @@ -5532,7 +5582,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (byte)((long)b[i])))); } } } @@ -6244,11 +6294,11 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte NEG(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } static byte neg(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6300,11 +6350,11 @@ public class ByteVector512Tests extends AbstractVectorTest { } static byte ABS(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } static byte abs(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6795,7 +6845,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6811,7 +6861,7 @@ public class ByteVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6891,7 +6941,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static long ADDReduceLong(byte[] a, int idx) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6900,7 +6950,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static long ADDReduceAllLong(byte[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((byte)res, (byte)ADDReduceLong(a, i)); } return res; @@ -6918,8 +6968,8 @@ public class ByteVector512Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6929,8 +6979,9 @@ public class ByteVector512Tests extends AbstractVectorTest { static long ADDReduceLongMasked(byte[] a, int idx, boolean[] mask) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6939,7 +6990,7 @@ public class ByteVector512Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(byte[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((byte)res, (byte)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6959,8 +7010,8 @@ public class ByteVector512Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ByteVector64Tests.java b/test/jdk/jdk/incubator/vector/ByteVector64Tests.java index ce671440d2e..e8ff81678cd 100644 --- a/test/jdk/jdk/incubator/vector/ByteVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/ByteVector64Tests.java @@ -1574,6 +1574,59 @@ public class ByteVector64Tests extends AbstractVectorTest { return a >= b; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + + static byte scalar_or(byte a, byte b) { + return (byte)(a | b); + } + + static byte scalar_and(byte a, byte b) { + return (byte)(a & b); + } + + static byte scalar_xor(byte a, byte b) { + return (byte)(a ^ b); + } + + static byte scalar_add(byte a, byte b) { + return (byte)(a + b); + } + + static byte scalar_sub(byte a, byte b) { + return (byte)(a - b); + } + + static byte scalar_mul(byte a, byte b) { + return (byte)(a * b); + } + + static byte scalar_min(byte a, byte b) { + return (byte)(Math.min(a, b)); + } + + static byte scalar_max(byte a, byte b) { + return (byte)(Math.max(a, b)); + } + + static byte scalar_div(byte a, byte b) { + return (byte)(a / b); + } + + static byte scalar_fma(byte a, byte b, byte c) { + return (byte)(Math.fma(a, b, c)); + } + + static byte scalar_abs(byte a) { + return (byte)(Math.abs(a)); + } + + static byte scalar_neg(byte a) { + return ((byte)-a); + } + + static boolean ult(byte a, byte b) { return Byte.compareUnsigned(a, b) < 0; } @@ -1590,9 +1643,6 @@ public class ByteVector64Tests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } - static byte firstNonZero(byte a, byte b) { - return Byte.compare(a, (byte) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1701,7 +1751,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte ADD(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1722,7 +1772,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte add(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1779,7 +1829,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte SUB(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1800,7 +1850,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte sub(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1857,7 +1907,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte MUL(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1878,7 +1928,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte mul(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -2025,7 +2075,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte FIRST_NONZERO(byte a, byte b) { - return (byte)((a)!=0?a:b); + return (byte)(firstNonZero(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3239,7 +3289,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte MIN(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3260,7 +3310,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte min(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3279,7 +3329,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte MAX(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3300,7 +3350,7 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte max(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3668,7 +3718,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ANDReduce(byte[] a, int idx) { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3677,7 +3727,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ANDReduceAll(byte[] a) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3695,7 +3745,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3708,20 +3758,20 @@ public class ByteVector64Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = AND_IDENTITY; - assertEquals((byte) (id & id), id, + assertEquals((byte) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id & x), x); - assertEquals((byte) (x & id), x); + assertEquals((byte) (scalar_and(id, x)), x); + assertEquals((byte) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id & x), x, + assertEquals((byte) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x & id), x, + assertEquals((byte) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3730,7 +3780,7 @@ public class ByteVector64Tests extends AbstractVectorTest { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3739,7 +3789,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ANDReduceAllMasked(byte[] a, boolean[] mask) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3759,7 +3809,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3770,7 +3820,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ORReduce(byte[] a, int idx) { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3779,7 +3829,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ORReduceAll(byte[] a) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3797,7 +3847,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3810,20 +3860,20 @@ public class ByteVector64Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = OR_IDENTITY; - assertEquals((byte) (id | id), id, + assertEquals((byte) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id | x), x); - assertEquals((byte) (x | id), x); + assertEquals((byte) (scalar_or(id, x)), x); + assertEquals((byte) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id | x), x, + assertEquals((byte) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x | id), x, + assertEquals((byte) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3832,7 +3882,7 @@ public class ByteVector64Tests extends AbstractVectorTest { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3841,7 +3891,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ORReduceAllMasked(byte[] a, boolean[] mask) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3861,7 +3911,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3872,7 +3922,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte XORReduce(byte[] a, int idx) { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3881,7 +3931,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte XORReduceAll(byte[] a) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3899,7 +3949,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3912,20 +3962,20 @@ public class ByteVector64Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = XOR_IDENTITY; - assertEquals((byte) (id ^ id), id, + assertEquals((byte) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id ^ x), x); - assertEquals((byte) (x ^ id), x); + assertEquals((byte) (scalar_xor(id, x)), x); + assertEquals((byte) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id ^ x), x, + assertEquals((byte) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x ^ id), x, + assertEquals((byte) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3934,7 +3984,7 @@ public class ByteVector64Tests extends AbstractVectorTest { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3943,7 +3993,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte XORReduceAllMasked(byte[] a, boolean[] mask) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3963,7 +4013,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3974,7 +4024,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ADDReduce(byte[] a, int idx) { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3983,7 +4033,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ADDReduceAll(byte[] a) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4001,7 +4051,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4014,20 +4064,20 @@ public class ByteVector64Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = ADD_IDENTITY; - assertEquals((byte) (id + id), id, + assertEquals((byte) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id + x), x); - assertEquals((byte) (x + id), x); + assertEquals((byte) (scalar_add(id, x)), x); + assertEquals((byte) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id + x), x, + assertEquals((byte) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x + id), x, + assertEquals((byte) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4036,7 +4086,7 @@ public class ByteVector64Tests extends AbstractVectorTest { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4045,7 +4095,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte ADDReduceAllMasked(byte[] a, boolean[] mask) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4065,7 +4115,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4076,7 +4126,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MULReduce(byte[] a, int idx) { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4085,7 +4135,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MULReduceAll(byte[] a) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4103,7 +4153,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4116,20 +4166,20 @@ public class ByteVector64Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MUL_IDENTITY; - assertEquals((byte) (id * id), id, + assertEquals((byte) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id * x), x); - assertEquals((byte) (x * id), x); + assertEquals((byte) (scalar_mul(id, x)), x); + assertEquals((byte) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id * x), x, + assertEquals((byte) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x * id), x, + assertEquals((byte) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4138,7 +4188,7 @@ public class ByteVector64Tests extends AbstractVectorTest { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4147,7 +4197,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MULReduceAllMasked(byte[] a, boolean[] mask) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4167,7 +4217,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4178,7 +4228,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4187,7 +4237,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4205,7 +4255,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4218,20 +4268,20 @@ public class ByteVector64Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MIN_IDENTITY; - assertEquals((byte) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.min(id, x), x); - assertEquals((byte) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4240,7 +4290,7 @@ public class ByteVector64Tests extends AbstractVectorTest { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4249,7 +4299,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4269,7 +4319,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4280,7 +4330,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4289,7 +4339,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4307,7 +4357,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4320,20 +4370,20 @@ public class ByteVector64Tests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MAX_IDENTITY; - assertEquals((byte) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.max(id, x), x); - assertEquals((byte) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4342,7 +4392,7 @@ public class ByteVector64Tests extends AbstractVectorTest { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4351,7 +4401,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4371,7 +4421,7 @@ public class ByteVector64Tests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5404,7 +5454,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5424,7 +5474,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5440,7 +5490,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (byte)((long)b[i]))); } } } @@ -5460,7 +5510,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (byte)((long)b[i])))); } } } @@ -5476,7 +5526,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5496,7 +5546,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5512,7 +5562,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (byte)((long)b[i]))); } } } @@ -5532,7 +5582,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (byte)((long)b[i])))); } } } @@ -6244,11 +6294,11 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte NEG(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } static byte neg(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6300,11 +6350,11 @@ public class ByteVector64Tests extends AbstractVectorTest { } static byte ABS(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } static byte abs(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6795,7 +6845,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6811,7 +6861,7 @@ public class ByteVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6891,7 +6941,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static long ADDReduceLong(byte[] a, int idx) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6900,7 +6950,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static long ADDReduceAllLong(byte[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((byte)res, (byte)ADDReduceLong(a, i)); } return res; @@ -6918,8 +6968,8 @@ public class ByteVector64Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6929,8 +6979,9 @@ public class ByteVector64Tests extends AbstractVectorTest { static long ADDReduceLongMasked(byte[] a, int idx, boolean[] mask) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6939,7 +6990,7 @@ public class ByteVector64Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(byte[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((byte)res, (byte)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6959,8 +7010,8 @@ public class ByteVector64Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java b/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java index c2d8188c090..c53710c3fdd 100644 --- a/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/ByteVectorMaxTests.java @@ -1580,6 +1580,59 @@ public class ByteVectorMaxTests extends AbstractVectorTest { return a >= b; } + static byte firstNonZero(byte a, byte b) { + return Byte.compare(a, (byte) 0) != 0 ? a : b; + } + + static byte scalar_or(byte a, byte b) { + return (byte)(a | b); + } + + static byte scalar_and(byte a, byte b) { + return (byte)(a & b); + } + + static byte scalar_xor(byte a, byte b) { + return (byte)(a ^ b); + } + + static byte scalar_add(byte a, byte b) { + return (byte)(a + b); + } + + static byte scalar_sub(byte a, byte b) { + return (byte)(a - b); + } + + static byte scalar_mul(byte a, byte b) { + return (byte)(a * b); + } + + static byte scalar_min(byte a, byte b) { + return (byte)(Math.min(a, b)); + } + + static byte scalar_max(byte a, byte b) { + return (byte)(Math.max(a, b)); + } + + static byte scalar_div(byte a, byte b) { + return (byte)(a / b); + } + + static byte scalar_fma(byte a, byte b, byte c) { + return (byte)(Math.fma(a, b, c)); + } + + static byte scalar_abs(byte a) { + return (byte)(Math.abs(a)); + } + + static byte scalar_neg(byte a) { + return ((byte)-a); + } + + static boolean ult(byte a, byte b) { return Byte.compareUnsigned(a, b) < 0; } @@ -1596,9 +1649,6 @@ public class ByteVectorMaxTests extends AbstractVectorTest { return Byte.compareUnsigned(a, b) >= 0; } - static byte firstNonZero(byte a, byte b) { - return Byte.compare(a, (byte) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1707,7 +1757,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte ADD(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1728,7 +1778,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte add(byte a, byte b) { - return (byte)(a + b); + return (byte)(scalar_add(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1785,7 +1835,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte SUB(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1806,7 +1856,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte sub(byte a, byte b) { - return (byte)(a - b); + return (byte)(scalar_sub(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1863,7 +1913,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte MUL(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -1884,7 +1934,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte mul(byte a, byte b) { - return (byte)(a * b); + return (byte)(scalar_mul(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -2031,7 +2081,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte FIRST_NONZERO(byte a, byte b) { - return (byte)((a)!=0?a:b); + return (byte)(firstNonZero(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3245,7 +3295,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte MIN(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3266,7 +3316,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte min(byte a, byte b) { - return (byte)(Math.min(a, b)); + return (byte)(scalar_min(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3285,7 +3335,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte MAX(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3306,7 +3356,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte max(byte a, byte b) { - return (byte)(Math.max(a, b)); + return (byte)(scalar_max(a, b)); } @Test(dataProvider = "byteBinaryOpProvider") @@ -3674,7 +3724,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ANDReduce(byte[] a, int idx) { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3683,7 +3733,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ANDReduceAll(byte[] a) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3701,7 +3751,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3714,20 +3764,20 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = AND_IDENTITY; - assertEquals((byte) (id & id), id, + assertEquals((byte) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id & x), x); - assertEquals((byte) (x & id), x); + assertEquals((byte) (scalar_and(id, x)), x); + assertEquals((byte) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id & x), x, + assertEquals((byte) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x & id), x, + assertEquals((byte) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3736,7 +3786,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3745,7 +3795,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ANDReduceAllMasked(byte[] a, boolean[] mask) { byte res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3765,7 +3815,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3776,7 +3826,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ORReduce(byte[] a, int idx) { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3785,7 +3835,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ORReduceAll(byte[] a) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3803,7 +3853,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3816,20 +3866,20 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = OR_IDENTITY; - assertEquals((byte) (id | id), id, + assertEquals((byte) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id | x), x); - assertEquals((byte) (x | id), x); + assertEquals((byte) (scalar_or(id, x)), x); + assertEquals((byte) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id | x), x, + assertEquals((byte) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x | id), x, + assertEquals((byte) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3838,7 +3888,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3847,7 +3897,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ORReduceAllMasked(byte[] a, boolean[] mask) { byte res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3867,7 +3917,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3878,7 +3928,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte XORReduce(byte[] a, int idx) { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3887,7 +3937,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte XORReduceAll(byte[] a) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3905,7 +3955,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3918,20 +3968,20 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = XOR_IDENTITY; - assertEquals((byte) (id ^ id), id, + assertEquals((byte) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id ^ x), x); - assertEquals((byte) (x ^ id), x); + assertEquals((byte) (scalar_xor(id, x)), x); + assertEquals((byte) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id ^ x), x, + assertEquals((byte) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x ^ id), x, + assertEquals((byte) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3940,7 +3990,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3949,7 +3999,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte XORReduceAllMasked(byte[] a, boolean[] mask) { byte res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3969,7 +4019,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3980,7 +4030,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ADDReduce(byte[] a, int idx) { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3989,7 +4039,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ADDReduceAll(byte[] a) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4007,7 +4057,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4020,20 +4070,20 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = ADD_IDENTITY; - assertEquals((byte) (id + id), id, + assertEquals((byte) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id + x), x); - assertEquals((byte) (x + id), x); + assertEquals((byte) (scalar_add(id, x)), x); + assertEquals((byte) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id + x), x, + assertEquals((byte) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x + id), x, + assertEquals((byte) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4042,7 +4092,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4051,7 +4101,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte ADDReduceAllMasked(byte[] a, boolean[] mask) { byte res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4071,7 +4121,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4082,7 +4132,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MULReduce(byte[] a, int idx) { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4091,7 +4141,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MULReduceAll(byte[] a) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4109,7 +4159,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4122,20 +4172,20 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MUL_IDENTITY; - assertEquals((byte) (id * id), id, + assertEquals((byte) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) (id * x), x); - assertEquals((byte) (x * id), x); + assertEquals((byte) (scalar_mul(id, x)), x); + assertEquals((byte) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((byte) (id * x), x, + assertEquals((byte) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((byte) (x * id), x, + assertEquals((byte) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4144,7 +4194,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4153,7 +4203,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MULReduceAllMasked(byte[] a, boolean[] mask) { byte res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4173,7 +4223,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4184,7 +4234,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MINReduce(byte[] a, int idx) { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4193,7 +4243,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MINReduceAll(byte[] a) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4211,7 +4261,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4224,20 +4274,20 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MIN_IDENTITY; - assertEquals((byte) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.min(id, x), x); - assertEquals((byte) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4246,7 +4296,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4255,7 +4305,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MINReduceAllMasked(byte[] a, boolean[] mask) { byte res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4275,7 +4325,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (byte) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4286,7 +4336,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MAXReduce(byte[] a, int idx) { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4295,7 +4345,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MAXReduceAll(byte[] a) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4313,7 +4363,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4326,20 +4376,20 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte[] a = fa.apply(SPECIES.length()); byte id = MAX_IDENTITY; - assertEquals((byte) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); byte x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((byte) Math.max(id, x), x); - assertEquals((byte) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((byte) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((byte) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4348,7 +4398,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { byte res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (byte) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4357,7 +4407,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static byte MAXReduceAllMasked(byte[] a, boolean[] mask) { byte res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (byte) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4377,7 +4427,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { ByteVector av = ByteVector.fromArray(SPECIES, a, i); byte v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (byte) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5410,7 +5460,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5430,7 +5480,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5446,7 +5496,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (byte)((long)b[i]))); } } } @@ -5466,7 +5516,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (byte)((long)b[i])))); } } } @@ -5482,7 +5532,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5502,7 +5552,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5518,7 +5568,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (byte)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (byte)((long)b[i]))); } } } @@ -5538,7 +5588,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (byte)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (byte)((long)b[i])))); } } } @@ -6250,11 +6300,11 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte NEG(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } static byte neg(byte a) { - return (byte)(-((byte)a)); + return (byte)(scalar_neg((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6306,11 +6356,11 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } static byte ABS(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } static byte abs(byte a) { - return (byte)(Math.abs((byte)a)); + return (byte)(scalar_abs((byte)a)); } @Test(dataProvider = "byteUnaryOpProvider") @@ -6801,7 +6851,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6817,7 +6867,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6897,7 +6947,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static long ADDReduceLong(byte[] a, int idx) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6906,7 +6956,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static long ADDReduceAllLong(byte[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((byte)res, (byte)ADDReduceLong(a, i)); } return res; @@ -6924,8 +6974,8 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6935,8 +6985,9 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static long ADDReduceLongMasked(byte[] a, int idx, boolean[] mask) { byte res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6945,7 +6996,7 @@ public class ByteVectorMaxTests extends AbstractVectorTest { static long ADDReduceAllLongMasked(byte[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((byte)res, (byte)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6965,8 +7016,8 @@ public class ByteVectorMaxTests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((byte)ra, (byte)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java index 7b4b587b142..1457e5a51ca 100644 --- a/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/DoubleVector128Tests.java @@ -1584,6 +1584,205 @@ relativeError)); return Double.compare(a, (double) 0) != 0 ? a : b; } + + static double scalar_add(double a, double b) { + return (double)(a + b); + } + + static double scalar_sub(double a, double b) { + return (double)(a - b); + } + + static double scalar_mul(double a, double b) { + return (double)(a * b); + } + + static double scalar_min(double a, double b) { + return (double)(Math.min(a, b)); + } + + static double scalar_max(double a, double b) { + return (double)(Math.max(a, b)); + } + + static double scalar_div(double a, double b) { + return (double)(a / b); + } + + static double scalar_fma(double a, double b, double c) { + return (double)(Math.fma(a, b, c)); + } + + static double scalar_abs(double a) { + return (double)(Math.abs(a)); + } + + static double scalar_neg(double a) { + return ((double)-a); + } + + static double scalar_sin(double a) { + return (double)Math.sin((double)a); + } + + static double scalar_exp(double a) { + return (double)Math.exp((double)a); + } + + static double scalar_log1p(double a) { + return (double)Math.log1p((double)a); + } + + static double scalar_log(double a) { + return (double)Math.log((double)a); + } + + static double scalar_log10(double a) { + return (double)Math.log10((double)a); + } + + static double scalar_expm1(double a) { + return (double)Math.expm1((double)a); + } + + static double scalar_cos(double a) { + return (double)Math.cos((double)a); + } + + static double scalar_tan(double a) { + return (double)Math.tan((double)a); + } + + static double scalar_sinh(double a) { + return (double)Math.sinh((double)a); + } + + static double scalar_cosh(double a) { + return (double)Math.cosh((double)a); + } + + static double scalar_tanh(double a) { + return (double)Math.tanh((double)a); + } + + static double scalar_asin(double a) { + return (double)Math.asin((double)a); + } + + static double scalar_acos(double a) { + return (double)Math.acos((double)a); + } + + static double scalar_atan(double a) { + return (double)Math.atan((double)a); + } + + static double scalar_cbrt(double a) { + return (double)Math.cbrt((double)a); + } + + static double scalar_sqrt(double a) { + return (double)Math.sqrt((double)a); + } + + static double scalar_hypot(double a, double b) { + return (double)Math.hypot((double)a, (double)b); + } + + static double scalar_pow(double a, double b) { + return (double)Math.pow((double)a, (double)b); + } + + static double scalar_atan2(double a, double b) { + return (double)Math.atan2((double)a, (double)b); + } + + static double strict_scalar_sin(double a) { + return (double)StrictMath.sin((double)a); + } + + static double strict_scalar_exp(double a) { + return (double)StrictMath.exp((double)a); + } + + static double strict_scalar_log1p(double a) { + return (double)StrictMath.log1p((double)a); + } + + static double strict_scalar_log(double a) { + return (double)StrictMath.log((double)a); + } + + static double strict_scalar_log10(double a) { + return (double)StrictMath.log10((double)a); + } + + static double strict_scalar_expm1(double a) { + return (double)StrictMath.expm1((double)a); + } + + static double strict_scalar_cos(double a) { + return (double)StrictMath.cos((double)a); + } + + static double strict_scalar_tan(double a) { + return (double)StrictMath.tan((double)a); + } + + static double strict_scalar_sinh(double a) { + return (double)StrictMath.sinh((double)a); + } + + static double strict_scalar_cosh(double a) { + return (double)StrictMath.cosh((double)a); + } + + static double strict_scalar_tanh(double a) { + return (double)StrictMath.tanh((double)a); + } + + static double strict_scalar_asin(double a) { + return (double)StrictMath.asin((double)a); + } + + static double strict_scalar_acos(double a) { + return (double)StrictMath.acos((double)a); + } + + static double strict_scalar_atan(double a) { + return (double)StrictMath.atan((double)a); + } + + static double strict_scalar_cbrt(double a) { + return (double)StrictMath.cbrt((double)a); + } + + static double strict_scalar_sqrt(double a) { + return (double)StrictMath.sqrt((double)a); + } + + static double strict_scalar_hypot(double a, double b) { + return (double)StrictMath.hypot((double)a, (double)b); + } + + static double strict_scalar_pow(double a, double b) { + return (double)StrictMath.pow((double)a, (double)b); + } + + static double strict_scalar_atan2(double a, double b) { + return (double)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(double a) { + return Double.isNaN(a); + } + static boolean isFinite(double a) { + return Double.isFinite(a); + } + static boolean isInfinite(double a) { + return Double.isInfinite(a); + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -1677,7 +1876,7 @@ relativeError)); } static double ADD(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1698,7 +1897,7 @@ relativeError)); } static double add(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1755,7 +1954,7 @@ relativeError)); } static double SUB(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1776,7 +1975,7 @@ relativeError)); } static double sub(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1833,7 +2032,7 @@ relativeError)); } static double MUL(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1854,7 +2053,7 @@ relativeError)); } static double mul(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1911,7 +2110,7 @@ relativeError)); } static double DIV(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1932,7 +2131,7 @@ relativeError)); } static double div(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1989,7 +2188,7 @@ relativeError)); } static double FIRST_NONZERO(double a, double b) { - return (double)(Double.doubleToLongBits(a)!=0?a:b); + return (double)(firstNonZero(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2291,7 +2490,7 @@ relativeError)); } static double MIN(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2312,7 +2511,7 @@ relativeError)); } static double min(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2331,7 +2530,7 @@ relativeError)); } static double MAX(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2352,7 +2551,7 @@ relativeError)); } static double max(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2429,7 +2628,7 @@ relativeError)); static double ADDReduce(double[] a, int idx) { double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2438,7 +2637,7 @@ relativeError)); static double ADDReduceAll(double[] a) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2456,7 +2655,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2469,20 +2668,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = ADD_IDENTITY; - assertEquals((double) (id + id), id, + assertEquals((double) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id + x), x); - assertEquals((double) (x + id), x); + assertEquals((double) (scalar_add(id, x)), x); + assertEquals((double) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id + x), x, + assertEquals((double) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x + id), x, + assertEquals((double) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2491,7 +2690,7 @@ relativeError)); double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2500,7 +2699,7 @@ relativeError)); static double ADDReduceAllMasked(double[] a, boolean[] mask) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2520,7 +2719,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2531,7 +2730,7 @@ relativeError)); static double MULReduce(double[] a, int idx) { double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2540,7 +2739,7 @@ relativeError)); static double MULReduceAll(double[] a) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2558,7 +2757,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2571,20 +2770,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MUL_IDENTITY; - assertEquals((double) (id * id), id, + assertEquals((double) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id * x), x); - assertEquals((double) (x * id), x); + assertEquals((double) (scalar_mul(id, x)), x); + assertEquals((double) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id * x), x, + assertEquals((double) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x * id), x, + assertEquals((double) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2593,7 +2792,7 @@ relativeError)); double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2602,7 +2801,7 @@ relativeError)); static double MULReduceAllMasked(double[] a, boolean[] mask) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2622,7 +2821,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2633,7 +2832,7 @@ relativeError)); static double MINReduce(double[] a, int idx) { double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2642,7 +2841,7 @@ relativeError)); static double MINReduceAll(double[] a) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2660,7 +2859,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2673,20 +2872,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MIN_IDENTITY; - assertEquals((double) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.min(id, x), x); - assertEquals((double) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2695,7 +2894,7 @@ relativeError)); double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2704,7 +2903,7 @@ relativeError)); static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2724,7 +2923,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2735,7 +2934,7 @@ relativeError)); static double MAXReduce(double[] a, int idx) { double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2744,7 +2943,7 @@ relativeError)); static double MAXReduceAll(double[] a) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2762,7 +2961,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2775,20 +2974,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MAX_IDENTITY; - assertEquals((double) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.max(id, x), x); - assertEquals((double) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2797,7 +2996,7 @@ relativeError)); double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2806,7 +3005,7 @@ relativeError)); static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2826,7 +3025,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3038,7 +3237,7 @@ relativeError)); } static boolean testIS_FINITE(double a) { - return Double.isFinite(a); + return isFinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3079,7 +3278,7 @@ relativeError)); } static boolean testIS_NAN(double a) { - return Double.isNaN(a); + return isNaN(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3120,7 +3319,7 @@ relativeError)); } static boolean testIS_INFINITE(double a) { - return Double.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3461,7 +3660,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3481,7 +3680,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3497,7 +3696,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (double)((long)b[i]))); } } } @@ -3517,7 +3716,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (double)((long)b[i])))); } } } @@ -3533,7 +3732,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3553,7 +3752,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3569,7 +3768,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (double)((long)b[i]))); } } } @@ -3589,7 +3788,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (double)((long)b[i])))); } } } @@ -4089,11 +4288,11 @@ relativeError)); } static double SIN(double a) { - return (double)(Math.sin((double)a)); + return (double)(scalar_sin(a)); } static double strictSIN(double a) { - return (double)(StrictMath.sin((double)a)); + return (double)(strict_scalar_sin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4112,11 +4311,11 @@ relativeError)); } static double EXP(double a) { - return (double)(Math.exp((double)a)); + return (double)(scalar_exp(a)); } static double strictEXP(double a) { - return (double)(StrictMath.exp((double)a)); + return (double)(strict_scalar_exp(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4135,11 +4334,11 @@ relativeError)); } static double LOG1P(double a) { - return (double)(Math.log1p((double)a)); + return (double)(scalar_log1p(a)); } static double strictLOG1P(double a) { - return (double)(StrictMath.log1p((double)a)); + return (double)(strict_scalar_log1p(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4158,11 +4357,11 @@ relativeError)); } static double LOG(double a) { - return (double)(Math.log((double)a)); + return (double)(scalar_log(a)); } static double strictLOG(double a) { - return (double)(StrictMath.log((double)a)); + return (double)(strict_scalar_log(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4181,11 +4380,11 @@ relativeError)); } static double LOG10(double a) { - return (double)(Math.log10((double)a)); + return (double)(scalar_log10(a)); } static double strictLOG10(double a) { - return (double)(StrictMath.log10((double)a)); + return (double)(strict_scalar_log10(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4204,11 +4403,11 @@ relativeError)); } static double EXPM1(double a) { - return (double)(Math.expm1((double)a)); + return (double)(scalar_expm1(a)); } static double strictEXPM1(double a) { - return (double)(StrictMath.expm1((double)a)); + return (double)(strict_scalar_expm1(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4227,11 +4426,11 @@ relativeError)); } static double COS(double a) { - return (double)(Math.cos((double)a)); + return (double)(scalar_cos(a)); } static double strictCOS(double a) { - return (double)(StrictMath.cos((double)a)); + return (double)(strict_scalar_cos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4250,11 +4449,11 @@ relativeError)); } static double TAN(double a) { - return (double)(Math.tan((double)a)); + return (double)(scalar_tan(a)); } static double strictTAN(double a) { - return (double)(StrictMath.tan((double)a)); + return (double)(strict_scalar_tan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4273,11 +4472,11 @@ relativeError)); } static double SINH(double a) { - return (double)(Math.sinh((double)a)); + return (double)(scalar_sinh(a)); } static double strictSINH(double a) { - return (double)(StrictMath.sinh((double)a)); + return (double)(strict_scalar_sinh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4296,11 +4495,11 @@ relativeError)); } static double COSH(double a) { - return (double)(Math.cosh((double)a)); + return (double)(scalar_cosh(a)); } static double strictCOSH(double a) { - return (double)(StrictMath.cosh((double)a)); + return (double)(strict_scalar_cosh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4319,11 +4518,11 @@ relativeError)); } static double TANH(double a) { - return (double)(Math.tanh((double)a)); + return (double)(scalar_tanh(a)); } static double strictTANH(double a) { - return (double)(StrictMath.tanh((double)a)); + return (double)(strict_scalar_tanh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4342,11 +4541,11 @@ relativeError)); } static double ASIN(double a) { - return (double)(Math.asin((double)a)); + return (double)(scalar_asin(a)); } static double strictASIN(double a) { - return (double)(StrictMath.asin((double)a)); + return (double)(strict_scalar_asin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4365,11 +4564,11 @@ relativeError)); } static double ACOS(double a) { - return (double)(Math.acos((double)a)); + return (double)(scalar_acos(a)); } static double strictACOS(double a) { - return (double)(StrictMath.acos((double)a)); + return (double)(strict_scalar_acos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4388,11 +4587,11 @@ relativeError)); } static double ATAN(double a) { - return (double)(Math.atan((double)a)); + return (double)(scalar_atan(a)); } static double strictATAN(double a) { - return (double)(StrictMath.atan((double)a)); + return (double)(strict_scalar_atan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4411,11 +4610,11 @@ relativeError)); } static double CBRT(double a) { - return (double)(Math.cbrt((double)a)); + return (double)(scalar_cbrt(a)); } static double strictCBRT(double a) { - return (double)(StrictMath.cbrt((double)a)); + return (double)(strict_scalar_cbrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4434,11 +4633,11 @@ relativeError)); } static double HYPOT(double a, double b) { - return (double)(Math.hypot((double)a, (double)b)); + return (double)(scalar_hypot(a, b)); } static double strictHYPOT(double a, double b) { - return (double)(StrictMath.hypot((double)a, (double)b)); + return (double)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4460,11 +4659,11 @@ relativeError)); static double POW(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictPOW(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4486,11 +4685,11 @@ relativeError)); static double pow(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictpow(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4512,11 +4711,11 @@ relativeError)); static double ATAN2(double a, double b) { - return (double)(Math.atan2((double)a, (double)b)); + return (double)(scalar_atan2(a, b)); } static double strictATAN2(double a, double b) { - return (double)(StrictMath.atan2((double)a, (double)b)); + return (double)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4568,11 +4767,11 @@ relativeError)); static double FMA(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } static double fma(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } @Test(dataProvider = "doubleTernaryOpProvider") @@ -4792,11 +4991,11 @@ relativeError)); } static double NEG(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } static double neg(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4848,11 +5047,11 @@ relativeError)); } static double ABS(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } static double abs(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4904,11 +5103,11 @@ relativeError)); } static double SQRT(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } static double sqrt(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -5121,7 +5320,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5137,7 +5336,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5196,7 +5395,7 @@ relativeError)); static long ADDReduceLong(double[] a, int idx) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5205,7 +5404,7 @@ relativeError)); static long ADDReduceAllLong(double[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((double)res, (double)ADDReduceLong(a, i)); } return res; @@ -5223,8 +5422,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5234,8 +5433,9 @@ relativeError)); static long ADDReduceLongMasked(double[] a, int idx, boolean[] mask) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5244,7 +5444,7 @@ relativeError)); static long ADDReduceAllLongMasked(double[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((double)res, (double)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5264,8 +5464,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java index 4d650d7b407..e417abe52e6 100644 --- a/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/DoubleVector256Tests.java @@ -1584,6 +1584,205 @@ relativeError)); return Double.compare(a, (double) 0) != 0 ? a : b; } + + static double scalar_add(double a, double b) { + return (double)(a + b); + } + + static double scalar_sub(double a, double b) { + return (double)(a - b); + } + + static double scalar_mul(double a, double b) { + return (double)(a * b); + } + + static double scalar_min(double a, double b) { + return (double)(Math.min(a, b)); + } + + static double scalar_max(double a, double b) { + return (double)(Math.max(a, b)); + } + + static double scalar_div(double a, double b) { + return (double)(a / b); + } + + static double scalar_fma(double a, double b, double c) { + return (double)(Math.fma(a, b, c)); + } + + static double scalar_abs(double a) { + return (double)(Math.abs(a)); + } + + static double scalar_neg(double a) { + return ((double)-a); + } + + static double scalar_sin(double a) { + return (double)Math.sin((double)a); + } + + static double scalar_exp(double a) { + return (double)Math.exp((double)a); + } + + static double scalar_log1p(double a) { + return (double)Math.log1p((double)a); + } + + static double scalar_log(double a) { + return (double)Math.log((double)a); + } + + static double scalar_log10(double a) { + return (double)Math.log10((double)a); + } + + static double scalar_expm1(double a) { + return (double)Math.expm1((double)a); + } + + static double scalar_cos(double a) { + return (double)Math.cos((double)a); + } + + static double scalar_tan(double a) { + return (double)Math.tan((double)a); + } + + static double scalar_sinh(double a) { + return (double)Math.sinh((double)a); + } + + static double scalar_cosh(double a) { + return (double)Math.cosh((double)a); + } + + static double scalar_tanh(double a) { + return (double)Math.tanh((double)a); + } + + static double scalar_asin(double a) { + return (double)Math.asin((double)a); + } + + static double scalar_acos(double a) { + return (double)Math.acos((double)a); + } + + static double scalar_atan(double a) { + return (double)Math.atan((double)a); + } + + static double scalar_cbrt(double a) { + return (double)Math.cbrt((double)a); + } + + static double scalar_sqrt(double a) { + return (double)Math.sqrt((double)a); + } + + static double scalar_hypot(double a, double b) { + return (double)Math.hypot((double)a, (double)b); + } + + static double scalar_pow(double a, double b) { + return (double)Math.pow((double)a, (double)b); + } + + static double scalar_atan2(double a, double b) { + return (double)Math.atan2((double)a, (double)b); + } + + static double strict_scalar_sin(double a) { + return (double)StrictMath.sin((double)a); + } + + static double strict_scalar_exp(double a) { + return (double)StrictMath.exp((double)a); + } + + static double strict_scalar_log1p(double a) { + return (double)StrictMath.log1p((double)a); + } + + static double strict_scalar_log(double a) { + return (double)StrictMath.log((double)a); + } + + static double strict_scalar_log10(double a) { + return (double)StrictMath.log10((double)a); + } + + static double strict_scalar_expm1(double a) { + return (double)StrictMath.expm1((double)a); + } + + static double strict_scalar_cos(double a) { + return (double)StrictMath.cos((double)a); + } + + static double strict_scalar_tan(double a) { + return (double)StrictMath.tan((double)a); + } + + static double strict_scalar_sinh(double a) { + return (double)StrictMath.sinh((double)a); + } + + static double strict_scalar_cosh(double a) { + return (double)StrictMath.cosh((double)a); + } + + static double strict_scalar_tanh(double a) { + return (double)StrictMath.tanh((double)a); + } + + static double strict_scalar_asin(double a) { + return (double)StrictMath.asin((double)a); + } + + static double strict_scalar_acos(double a) { + return (double)StrictMath.acos((double)a); + } + + static double strict_scalar_atan(double a) { + return (double)StrictMath.atan((double)a); + } + + static double strict_scalar_cbrt(double a) { + return (double)StrictMath.cbrt((double)a); + } + + static double strict_scalar_sqrt(double a) { + return (double)StrictMath.sqrt((double)a); + } + + static double strict_scalar_hypot(double a, double b) { + return (double)StrictMath.hypot((double)a, (double)b); + } + + static double strict_scalar_pow(double a, double b) { + return (double)StrictMath.pow((double)a, (double)b); + } + + static double strict_scalar_atan2(double a, double b) { + return (double)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(double a) { + return Double.isNaN(a); + } + static boolean isFinite(double a) { + return Double.isFinite(a); + } + static boolean isInfinite(double a) { + return Double.isInfinite(a); + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -1677,7 +1876,7 @@ relativeError)); } static double ADD(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1698,7 +1897,7 @@ relativeError)); } static double add(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1755,7 +1954,7 @@ relativeError)); } static double SUB(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1776,7 +1975,7 @@ relativeError)); } static double sub(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1833,7 +2032,7 @@ relativeError)); } static double MUL(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1854,7 +2053,7 @@ relativeError)); } static double mul(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1911,7 +2110,7 @@ relativeError)); } static double DIV(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1932,7 +2131,7 @@ relativeError)); } static double div(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1989,7 +2188,7 @@ relativeError)); } static double FIRST_NONZERO(double a, double b) { - return (double)(Double.doubleToLongBits(a)!=0?a:b); + return (double)(firstNonZero(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2291,7 +2490,7 @@ relativeError)); } static double MIN(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2312,7 +2511,7 @@ relativeError)); } static double min(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2331,7 +2530,7 @@ relativeError)); } static double MAX(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2352,7 +2551,7 @@ relativeError)); } static double max(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2429,7 +2628,7 @@ relativeError)); static double ADDReduce(double[] a, int idx) { double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2438,7 +2637,7 @@ relativeError)); static double ADDReduceAll(double[] a) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2456,7 +2655,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2469,20 +2668,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = ADD_IDENTITY; - assertEquals((double) (id + id), id, + assertEquals((double) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id + x), x); - assertEquals((double) (x + id), x); + assertEquals((double) (scalar_add(id, x)), x); + assertEquals((double) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id + x), x, + assertEquals((double) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x + id), x, + assertEquals((double) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2491,7 +2690,7 @@ relativeError)); double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2500,7 +2699,7 @@ relativeError)); static double ADDReduceAllMasked(double[] a, boolean[] mask) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2520,7 +2719,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2531,7 +2730,7 @@ relativeError)); static double MULReduce(double[] a, int idx) { double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2540,7 +2739,7 @@ relativeError)); static double MULReduceAll(double[] a) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2558,7 +2757,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2571,20 +2770,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MUL_IDENTITY; - assertEquals((double) (id * id), id, + assertEquals((double) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id * x), x); - assertEquals((double) (x * id), x); + assertEquals((double) (scalar_mul(id, x)), x); + assertEquals((double) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id * x), x, + assertEquals((double) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x * id), x, + assertEquals((double) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2593,7 +2792,7 @@ relativeError)); double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2602,7 +2801,7 @@ relativeError)); static double MULReduceAllMasked(double[] a, boolean[] mask) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2622,7 +2821,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2633,7 +2832,7 @@ relativeError)); static double MINReduce(double[] a, int idx) { double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2642,7 +2841,7 @@ relativeError)); static double MINReduceAll(double[] a) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2660,7 +2859,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2673,20 +2872,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MIN_IDENTITY; - assertEquals((double) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.min(id, x), x); - assertEquals((double) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2695,7 +2894,7 @@ relativeError)); double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2704,7 +2903,7 @@ relativeError)); static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2724,7 +2923,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2735,7 +2934,7 @@ relativeError)); static double MAXReduce(double[] a, int idx) { double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2744,7 +2943,7 @@ relativeError)); static double MAXReduceAll(double[] a) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2762,7 +2961,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2775,20 +2974,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MAX_IDENTITY; - assertEquals((double) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.max(id, x), x); - assertEquals((double) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2797,7 +2996,7 @@ relativeError)); double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2806,7 +3005,7 @@ relativeError)); static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2826,7 +3025,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3038,7 +3237,7 @@ relativeError)); } static boolean testIS_FINITE(double a) { - return Double.isFinite(a); + return isFinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3079,7 +3278,7 @@ relativeError)); } static boolean testIS_NAN(double a) { - return Double.isNaN(a); + return isNaN(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3120,7 +3319,7 @@ relativeError)); } static boolean testIS_INFINITE(double a) { - return Double.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3461,7 +3660,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3481,7 +3680,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3497,7 +3696,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (double)((long)b[i]))); } } } @@ -3517,7 +3716,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (double)((long)b[i])))); } } } @@ -3533,7 +3732,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3553,7 +3752,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3569,7 +3768,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (double)((long)b[i]))); } } } @@ -3589,7 +3788,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (double)((long)b[i])))); } } } @@ -4089,11 +4288,11 @@ relativeError)); } static double SIN(double a) { - return (double)(Math.sin((double)a)); + return (double)(scalar_sin(a)); } static double strictSIN(double a) { - return (double)(StrictMath.sin((double)a)); + return (double)(strict_scalar_sin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4112,11 +4311,11 @@ relativeError)); } static double EXP(double a) { - return (double)(Math.exp((double)a)); + return (double)(scalar_exp(a)); } static double strictEXP(double a) { - return (double)(StrictMath.exp((double)a)); + return (double)(strict_scalar_exp(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4135,11 +4334,11 @@ relativeError)); } static double LOG1P(double a) { - return (double)(Math.log1p((double)a)); + return (double)(scalar_log1p(a)); } static double strictLOG1P(double a) { - return (double)(StrictMath.log1p((double)a)); + return (double)(strict_scalar_log1p(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4158,11 +4357,11 @@ relativeError)); } static double LOG(double a) { - return (double)(Math.log((double)a)); + return (double)(scalar_log(a)); } static double strictLOG(double a) { - return (double)(StrictMath.log((double)a)); + return (double)(strict_scalar_log(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4181,11 +4380,11 @@ relativeError)); } static double LOG10(double a) { - return (double)(Math.log10((double)a)); + return (double)(scalar_log10(a)); } static double strictLOG10(double a) { - return (double)(StrictMath.log10((double)a)); + return (double)(strict_scalar_log10(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4204,11 +4403,11 @@ relativeError)); } static double EXPM1(double a) { - return (double)(Math.expm1((double)a)); + return (double)(scalar_expm1(a)); } static double strictEXPM1(double a) { - return (double)(StrictMath.expm1((double)a)); + return (double)(strict_scalar_expm1(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4227,11 +4426,11 @@ relativeError)); } static double COS(double a) { - return (double)(Math.cos((double)a)); + return (double)(scalar_cos(a)); } static double strictCOS(double a) { - return (double)(StrictMath.cos((double)a)); + return (double)(strict_scalar_cos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4250,11 +4449,11 @@ relativeError)); } static double TAN(double a) { - return (double)(Math.tan((double)a)); + return (double)(scalar_tan(a)); } static double strictTAN(double a) { - return (double)(StrictMath.tan((double)a)); + return (double)(strict_scalar_tan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4273,11 +4472,11 @@ relativeError)); } static double SINH(double a) { - return (double)(Math.sinh((double)a)); + return (double)(scalar_sinh(a)); } static double strictSINH(double a) { - return (double)(StrictMath.sinh((double)a)); + return (double)(strict_scalar_sinh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4296,11 +4495,11 @@ relativeError)); } static double COSH(double a) { - return (double)(Math.cosh((double)a)); + return (double)(scalar_cosh(a)); } static double strictCOSH(double a) { - return (double)(StrictMath.cosh((double)a)); + return (double)(strict_scalar_cosh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4319,11 +4518,11 @@ relativeError)); } static double TANH(double a) { - return (double)(Math.tanh((double)a)); + return (double)(scalar_tanh(a)); } static double strictTANH(double a) { - return (double)(StrictMath.tanh((double)a)); + return (double)(strict_scalar_tanh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4342,11 +4541,11 @@ relativeError)); } static double ASIN(double a) { - return (double)(Math.asin((double)a)); + return (double)(scalar_asin(a)); } static double strictASIN(double a) { - return (double)(StrictMath.asin((double)a)); + return (double)(strict_scalar_asin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4365,11 +4564,11 @@ relativeError)); } static double ACOS(double a) { - return (double)(Math.acos((double)a)); + return (double)(scalar_acos(a)); } static double strictACOS(double a) { - return (double)(StrictMath.acos((double)a)); + return (double)(strict_scalar_acos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4388,11 +4587,11 @@ relativeError)); } static double ATAN(double a) { - return (double)(Math.atan((double)a)); + return (double)(scalar_atan(a)); } static double strictATAN(double a) { - return (double)(StrictMath.atan((double)a)); + return (double)(strict_scalar_atan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4411,11 +4610,11 @@ relativeError)); } static double CBRT(double a) { - return (double)(Math.cbrt((double)a)); + return (double)(scalar_cbrt(a)); } static double strictCBRT(double a) { - return (double)(StrictMath.cbrt((double)a)); + return (double)(strict_scalar_cbrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4434,11 +4633,11 @@ relativeError)); } static double HYPOT(double a, double b) { - return (double)(Math.hypot((double)a, (double)b)); + return (double)(scalar_hypot(a, b)); } static double strictHYPOT(double a, double b) { - return (double)(StrictMath.hypot((double)a, (double)b)); + return (double)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4460,11 +4659,11 @@ relativeError)); static double POW(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictPOW(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4486,11 +4685,11 @@ relativeError)); static double pow(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictpow(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4512,11 +4711,11 @@ relativeError)); static double ATAN2(double a, double b) { - return (double)(Math.atan2((double)a, (double)b)); + return (double)(scalar_atan2(a, b)); } static double strictATAN2(double a, double b) { - return (double)(StrictMath.atan2((double)a, (double)b)); + return (double)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4568,11 +4767,11 @@ relativeError)); static double FMA(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } static double fma(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } @Test(dataProvider = "doubleTernaryOpProvider") @@ -4792,11 +4991,11 @@ relativeError)); } static double NEG(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } static double neg(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4848,11 +5047,11 @@ relativeError)); } static double ABS(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } static double abs(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4904,11 +5103,11 @@ relativeError)); } static double SQRT(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } static double sqrt(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -5121,7 +5320,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5137,7 +5336,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5196,7 +5395,7 @@ relativeError)); static long ADDReduceLong(double[] a, int idx) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5205,7 +5404,7 @@ relativeError)); static long ADDReduceAllLong(double[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((double)res, (double)ADDReduceLong(a, i)); } return res; @@ -5223,8 +5422,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5234,8 +5433,9 @@ relativeError)); static long ADDReduceLongMasked(double[] a, int idx, boolean[] mask) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5244,7 +5444,7 @@ relativeError)); static long ADDReduceAllLongMasked(double[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((double)res, (double)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5264,8 +5464,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java index 534470e194c..d23b2bf1511 100644 --- a/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/DoubleVector512Tests.java @@ -1584,6 +1584,205 @@ relativeError)); return Double.compare(a, (double) 0) != 0 ? a : b; } + + static double scalar_add(double a, double b) { + return (double)(a + b); + } + + static double scalar_sub(double a, double b) { + return (double)(a - b); + } + + static double scalar_mul(double a, double b) { + return (double)(a * b); + } + + static double scalar_min(double a, double b) { + return (double)(Math.min(a, b)); + } + + static double scalar_max(double a, double b) { + return (double)(Math.max(a, b)); + } + + static double scalar_div(double a, double b) { + return (double)(a / b); + } + + static double scalar_fma(double a, double b, double c) { + return (double)(Math.fma(a, b, c)); + } + + static double scalar_abs(double a) { + return (double)(Math.abs(a)); + } + + static double scalar_neg(double a) { + return ((double)-a); + } + + static double scalar_sin(double a) { + return (double)Math.sin((double)a); + } + + static double scalar_exp(double a) { + return (double)Math.exp((double)a); + } + + static double scalar_log1p(double a) { + return (double)Math.log1p((double)a); + } + + static double scalar_log(double a) { + return (double)Math.log((double)a); + } + + static double scalar_log10(double a) { + return (double)Math.log10((double)a); + } + + static double scalar_expm1(double a) { + return (double)Math.expm1((double)a); + } + + static double scalar_cos(double a) { + return (double)Math.cos((double)a); + } + + static double scalar_tan(double a) { + return (double)Math.tan((double)a); + } + + static double scalar_sinh(double a) { + return (double)Math.sinh((double)a); + } + + static double scalar_cosh(double a) { + return (double)Math.cosh((double)a); + } + + static double scalar_tanh(double a) { + return (double)Math.tanh((double)a); + } + + static double scalar_asin(double a) { + return (double)Math.asin((double)a); + } + + static double scalar_acos(double a) { + return (double)Math.acos((double)a); + } + + static double scalar_atan(double a) { + return (double)Math.atan((double)a); + } + + static double scalar_cbrt(double a) { + return (double)Math.cbrt((double)a); + } + + static double scalar_sqrt(double a) { + return (double)Math.sqrt((double)a); + } + + static double scalar_hypot(double a, double b) { + return (double)Math.hypot((double)a, (double)b); + } + + static double scalar_pow(double a, double b) { + return (double)Math.pow((double)a, (double)b); + } + + static double scalar_atan2(double a, double b) { + return (double)Math.atan2((double)a, (double)b); + } + + static double strict_scalar_sin(double a) { + return (double)StrictMath.sin((double)a); + } + + static double strict_scalar_exp(double a) { + return (double)StrictMath.exp((double)a); + } + + static double strict_scalar_log1p(double a) { + return (double)StrictMath.log1p((double)a); + } + + static double strict_scalar_log(double a) { + return (double)StrictMath.log((double)a); + } + + static double strict_scalar_log10(double a) { + return (double)StrictMath.log10((double)a); + } + + static double strict_scalar_expm1(double a) { + return (double)StrictMath.expm1((double)a); + } + + static double strict_scalar_cos(double a) { + return (double)StrictMath.cos((double)a); + } + + static double strict_scalar_tan(double a) { + return (double)StrictMath.tan((double)a); + } + + static double strict_scalar_sinh(double a) { + return (double)StrictMath.sinh((double)a); + } + + static double strict_scalar_cosh(double a) { + return (double)StrictMath.cosh((double)a); + } + + static double strict_scalar_tanh(double a) { + return (double)StrictMath.tanh((double)a); + } + + static double strict_scalar_asin(double a) { + return (double)StrictMath.asin((double)a); + } + + static double strict_scalar_acos(double a) { + return (double)StrictMath.acos((double)a); + } + + static double strict_scalar_atan(double a) { + return (double)StrictMath.atan((double)a); + } + + static double strict_scalar_cbrt(double a) { + return (double)StrictMath.cbrt((double)a); + } + + static double strict_scalar_sqrt(double a) { + return (double)StrictMath.sqrt((double)a); + } + + static double strict_scalar_hypot(double a, double b) { + return (double)StrictMath.hypot((double)a, (double)b); + } + + static double strict_scalar_pow(double a, double b) { + return (double)StrictMath.pow((double)a, (double)b); + } + + static double strict_scalar_atan2(double a, double b) { + return (double)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(double a) { + return Double.isNaN(a); + } + static boolean isFinite(double a) { + return Double.isFinite(a); + } + static boolean isInfinite(double a) { + return Double.isInfinite(a); + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -1677,7 +1876,7 @@ relativeError)); } static double ADD(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1698,7 +1897,7 @@ relativeError)); } static double add(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1755,7 +1954,7 @@ relativeError)); } static double SUB(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1776,7 +1975,7 @@ relativeError)); } static double sub(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1833,7 +2032,7 @@ relativeError)); } static double MUL(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1854,7 +2053,7 @@ relativeError)); } static double mul(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1911,7 +2110,7 @@ relativeError)); } static double DIV(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1932,7 +2131,7 @@ relativeError)); } static double div(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1989,7 +2188,7 @@ relativeError)); } static double FIRST_NONZERO(double a, double b) { - return (double)(Double.doubleToLongBits(a)!=0?a:b); + return (double)(firstNonZero(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2291,7 +2490,7 @@ relativeError)); } static double MIN(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2312,7 +2511,7 @@ relativeError)); } static double min(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2331,7 +2530,7 @@ relativeError)); } static double MAX(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2352,7 +2551,7 @@ relativeError)); } static double max(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2429,7 +2628,7 @@ relativeError)); static double ADDReduce(double[] a, int idx) { double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2438,7 +2637,7 @@ relativeError)); static double ADDReduceAll(double[] a) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2456,7 +2655,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2469,20 +2668,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = ADD_IDENTITY; - assertEquals((double) (id + id), id, + assertEquals((double) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id + x), x); - assertEquals((double) (x + id), x); + assertEquals((double) (scalar_add(id, x)), x); + assertEquals((double) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id + x), x, + assertEquals((double) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x + id), x, + assertEquals((double) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2491,7 +2690,7 @@ relativeError)); double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2500,7 +2699,7 @@ relativeError)); static double ADDReduceAllMasked(double[] a, boolean[] mask) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2520,7 +2719,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2531,7 +2730,7 @@ relativeError)); static double MULReduce(double[] a, int idx) { double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2540,7 +2739,7 @@ relativeError)); static double MULReduceAll(double[] a) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2558,7 +2757,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2571,20 +2770,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MUL_IDENTITY; - assertEquals((double) (id * id), id, + assertEquals((double) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id * x), x); - assertEquals((double) (x * id), x); + assertEquals((double) (scalar_mul(id, x)), x); + assertEquals((double) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id * x), x, + assertEquals((double) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x * id), x, + assertEquals((double) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2593,7 +2792,7 @@ relativeError)); double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2602,7 +2801,7 @@ relativeError)); static double MULReduceAllMasked(double[] a, boolean[] mask) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2622,7 +2821,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2633,7 +2832,7 @@ relativeError)); static double MINReduce(double[] a, int idx) { double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2642,7 +2841,7 @@ relativeError)); static double MINReduceAll(double[] a) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2660,7 +2859,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2673,20 +2872,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MIN_IDENTITY; - assertEquals((double) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.min(id, x), x); - assertEquals((double) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2695,7 +2894,7 @@ relativeError)); double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2704,7 +2903,7 @@ relativeError)); static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2724,7 +2923,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2735,7 +2934,7 @@ relativeError)); static double MAXReduce(double[] a, int idx) { double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2744,7 +2943,7 @@ relativeError)); static double MAXReduceAll(double[] a) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2762,7 +2961,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2775,20 +2974,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MAX_IDENTITY; - assertEquals((double) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.max(id, x), x); - assertEquals((double) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2797,7 +2996,7 @@ relativeError)); double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2806,7 +3005,7 @@ relativeError)); static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2826,7 +3025,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3038,7 +3237,7 @@ relativeError)); } static boolean testIS_FINITE(double a) { - return Double.isFinite(a); + return isFinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3079,7 +3278,7 @@ relativeError)); } static boolean testIS_NAN(double a) { - return Double.isNaN(a); + return isNaN(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3120,7 +3319,7 @@ relativeError)); } static boolean testIS_INFINITE(double a) { - return Double.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3461,7 +3660,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3481,7 +3680,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3497,7 +3696,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (double)((long)b[i]))); } } } @@ -3517,7 +3716,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (double)((long)b[i])))); } } } @@ -3533,7 +3732,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3553,7 +3752,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3569,7 +3768,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (double)((long)b[i]))); } } } @@ -3589,7 +3788,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (double)((long)b[i])))); } } } @@ -4089,11 +4288,11 @@ relativeError)); } static double SIN(double a) { - return (double)(Math.sin((double)a)); + return (double)(scalar_sin(a)); } static double strictSIN(double a) { - return (double)(StrictMath.sin((double)a)); + return (double)(strict_scalar_sin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4112,11 +4311,11 @@ relativeError)); } static double EXP(double a) { - return (double)(Math.exp((double)a)); + return (double)(scalar_exp(a)); } static double strictEXP(double a) { - return (double)(StrictMath.exp((double)a)); + return (double)(strict_scalar_exp(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4135,11 +4334,11 @@ relativeError)); } static double LOG1P(double a) { - return (double)(Math.log1p((double)a)); + return (double)(scalar_log1p(a)); } static double strictLOG1P(double a) { - return (double)(StrictMath.log1p((double)a)); + return (double)(strict_scalar_log1p(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4158,11 +4357,11 @@ relativeError)); } static double LOG(double a) { - return (double)(Math.log((double)a)); + return (double)(scalar_log(a)); } static double strictLOG(double a) { - return (double)(StrictMath.log((double)a)); + return (double)(strict_scalar_log(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4181,11 +4380,11 @@ relativeError)); } static double LOG10(double a) { - return (double)(Math.log10((double)a)); + return (double)(scalar_log10(a)); } static double strictLOG10(double a) { - return (double)(StrictMath.log10((double)a)); + return (double)(strict_scalar_log10(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4204,11 +4403,11 @@ relativeError)); } static double EXPM1(double a) { - return (double)(Math.expm1((double)a)); + return (double)(scalar_expm1(a)); } static double strictEXPM1(double a) { - return (double)(StrictMath.expm1((double)a)); + return (double)(strict_scalar_expm1(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4227,11 +4426,11 @@ relativeError)); } static double COS(double a) { - return (double)(Math.cos((double)a)); + return (double)(scalar_cos(a)); } static double strictCOS(double a) { - return (double)(StrictMath.cos((double)a)); + return (double)(strict_scalar_cos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4250,11 +4449,11 @@ relativeError)); } static double TAN(double a) { - return (double)(Math.tan((double)a)); + return (double)(scalar_tan(a)); } static double strictTAN(double a) { - return (double)(StrictMath.tan((double)a)); + return (double)(strict_scalar_tan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4273,11 +4472,11 @@ relativeError)); } static double SINH(double a) { - return (double)(Math.sinh((double)a)); + return (double)(scalar_sinh(a)); } static double strictSINH(double a) { - return (double)(StrictMath.sinh((double)a)); + return (double)(strict_scalar_sinh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4296,11 +4495,11 @@ relativeError)); } static double COSH(double a) { - return (double)(Math.cosh((double)a)); + return (double)(scalar_cosh(a)); } static double strictCOSH(double a) { - return (double)(StrictMath.cosh((double)a)); + return (double)(strict_scalar_cosh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4319,11 +4518,11 @@ relativeError)); } static double TANH(double a) { - return (double)(Math.tanh((double)a)); + return (double)(scalar_tanh(a)); } static double strictTANH(double a) { - return (double)(StrictMath.tanh((double)a)); + return (double)(strict_scalar_tanh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4342,11 +4541,11 @@ relativeError)); } static double ASIN(double a) { - return (double)(Math.asin((double)a)); + return (double)(scalar_asin(a)); } static double strictASIN(double a) { - return (double)(StrictMath.asin((double)a)); + return (double)(strict_scalar_asin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4365,11 +4564,11 @@ relativeError)); } static double ACOS(double a) { - return (double)(Math.acos((double)a)); + return (double)(scalar_acos(a)); } static double strictACOS(double a) { - return (double)(StrictMath.acos((double)a)); + return (double)(strict_scalar_acos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4388,11 +4587,11 @@ relativeError)); } static double ATAN(double a) { - return (double)(Math.atan((double)a)); + return (double)(scalar_atan(a)); } static double strictATAN(double a) { - return (double)(StrictMath.atan((double)a)); + return (double)(strict_scalar_atan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4411,11 +4610,11 @@ relativeError)); } static double CBRT(double a) { - return (double)(Math.cbrt((double)a)); + return (double)(scalar_cbrt(a)); } static double strictCBRT(double a) { - return (double)(StrictMath.cbrt((double)a)); + return (double)(strict_scalar_cbrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4434,11 +4633,11 @@ relativeError)); } static double HYPOT(double a, double b) { - return (double)(Math.hypot((double)a, (double)b)); + return (double)(scalar_hypot(a, b)); } static double strictHYPOT(double a, double b) { - return (double)(StrictMath.hypot((double)a, (double)b)); + return (double)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4460,11 +4659,11 @@ relativeError)); static double POW(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictPOW(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4486,11 +4685,11 @@ relativeError)); static double pow(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictpow(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4512,11 +4711,11 @@ relativeError)); static double ATAN2(double a, double b) { - return (double)(Math.atan2((double)a, (double)b)); + return (double)(scalar_atan2(a, b)); } static double strictATAN2(double a, double b) { - return (double)(StrictMath.atan2((double)a, (double)b)); + return (double)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4568,11 +4767,11 @@ relativeError)); static double FMA(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } static double fma(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } @Test(dataProvider = "doubleTernaryOpProvider") @@ -4792,11 +4991,11 @@ relativeError)); } static double NEG(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } static double neg(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4848,11 +5047,11 @@ relativeError)); } static double ABS(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } static double abs(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4904,11 +5103,11 @@ relativeError)); } static double SQRT(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } static double sqrt(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -5121,7 +5320,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5137,7 +5336,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5196,7 +5395,7 @@ relativeError)); static long ADDReduceLong(double[] a, int idx) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5205,7 +5404,7 @@ relativeError)); static long ADDReduceAllLong(double[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((double)res, (double)ADDReduceLong(a, i)); } return res; @@ -5223,8 +5422,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5234,8 +5433,9 @@ relativeError)); static long ADDReduceLongMasked(double[] a, int idx, boolean[] mask) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5244,7 +5444,7 @@ relativeError)); static long ADDReduceAllLongMasked(double[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((double)res, (double)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5264,8 +5464,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java b/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java index 7f9f8986f1f..d2aff0b7ea5 100644 --- a/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/DoubleVector64Tests.java @@ -1584,6 +1584,205 @@ relativeError)); return Double.compare(a, (double) 0) != 0 ? a : b; } + + static double scalar_add(double a, double b) { + return (double)(a + b); + } + + static double scalar_sub(double a, double b) { + return (double)(a - b); + } + + static double scalar_mul(double a, double b) { + return (double)(a * b); + } + + static double scalar_min(double a, double b) { + return (double)(Math.min(a, b)); + } + + static double scalar_max(double a, double b) { + return (double)(Math.max(a, b)); + } + + static double scalar_div(double a, double b) { + return (double)(a / b); + } + + static double scalar_fma(double a, double b, double c) { + return (double)(Math.fma(a, b, c)); + } + + static double scalar_abs(double a) { + return (double)(Math.abs(a)); + } + + static double scalar_neg(double a) { + return ((double)-a); + } + + static double scalar_sin(double a) { + return (double)Math.sin((double)a); + } + + static double scalar_exp(double a) { + return (double)Math.exp((double)a); + } + + static double scalar_log1p(double a) { + return (double)Math.log1p((double)a); + } + + static double scalar_log(double a) { + return (double)Math.log((double)a); + } + + static double scalar_log10(double a) { + return (double)Math.log10((double)a); + } + + static double scalar_expm1(double a) { + return (double)Math.expm1((double)a); + } + + static double scalar_cos(double a) { + return (double)Math.cos((double)a); + } + + static double scalar_tan(double a) { + return (double)Math.tan((double)a); + } + + static double scalar_sinh(double a) { + return (double)Math.sinh((double)a); + } + + static double scalar_cosh(double a) { + return (double)Math.cosh((double)a); + } + + static double scalar_tanh(double a) { + return (double)Math.tanh((double)a); + } + + static double scalar_asin(double a) { + return (double)Math.asin((double)a); + } + + static double scalar_acos(double a) { + return (double)Math.acos((double)a); + } + + static double scalar_atan(double a) { + return (double)Math.atan((double)a); + } + + static double scalar_cbrt(double a) { + return (double)Math.cbrt((double)a); + } + + static double scalar_sqrt(double a) { + return (double)Math.sqrt((double)a); + } + + static double scalar_hypot(double a, double b) { + return (double)Math.hypot((double)a, (double)b); + } + + static double scalar_pow(double a, double b) { + return (double)Math.pow((double)a, (double)b); + } + + static double scalar_atan2(double a, double b) { + return (double)Math.atan2((double)a, (double)b); + } + + static double strict_scalar_sin(double a) { + return (double)StrictMath.sin((double)a); + } + + static double strict_scalar_exp(double a) { + return (double)StrictMath.exp((double)a); + } + + static double strict_scalar_log1p(double a) { + return (double)StrictMath.log1p((double)a); + } + + static double strict_scalar_log(double a) { + return (double)StrictMath.log((double)a); + } + + static double strict_scalar_log10(double a) { + return (double)StrictMath.log10((double)a); + } + + static double strict_scalar_expm1(double a) { + return (double)StrictMath.expm1((double)a); + } + + static double strict_scalar_cos(double a) { + return (double)StrictMath.cos((double)a); + } + + static double strict_scalar_tan(double a) { + return (double)StrictMath.tan((double)a); + } + + static double strict_scalar_sinh(double a) { + return (double)StrictMath.sinh((double)a); + } + + static double strict_scalar_cosh(double a) { + return (double)StrictMath.cosh((double)a); + } + + static double strict_scalar_tanh(double a) { + return (double)StrictMath.tanh((double)a); + } + + static double strict_scalar_asin(double a) { + return (double)StrictMath.asin((double)a); + } + + static double strict_scalar_acos(double a) { + return (double)StrictMath.acos((double)a); + } + + static double strict_scalar_atan(double a) { + return (double)StrictMath.atan((double)a); + } + + static double strict_scalar_cbrt(double a) { + return (double)StrictMath.cbrt((double)a); + } + + static double strict_scalar_sqrt(double a) { + return (double)StrictMath.sqrt((double)a); + } + + static double strict_scalar_hypot(double a, double b) { + return (double)StrictMath.hypot((double)a, (double)b); + } + + static double strict_scalar_pow(double a, double b) { + return (double)StrictMath.pow((double)a, (double)b); + } + + static double strict_scalar_atan2(double a, double b) { + return (double)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(double a) { + return Double.isNaN(a); + } + static boolean isFinite(double a) { + return Double.isFinite(a); + } + static boolean isInfinite(double a) { + return Double.isInfinite(a); + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -1677,7 +1876,7 @@ relativeError)); } static double ADD(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1698,7 +1897,7 @@ relativeError)); } static double add(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1755,7 +1954,7 @@ relativeError)); } static double SUB(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1776,7 +1975,7 @@ relativeError)); } static double sub(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1833,7 +2032,7 @@ relativeError)); } static double MUL(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1854,7 +2053,7 @@ relativeError)); } static double mul(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1911,7 +2110,7 @@ relativeError)); } static double DIV(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1932,7 +2131,7 @@ relativeError)); } static double div(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1989,7 +2188,7 @@ relativeError)); } static double FIRST_NONZERO(double a, double b) { - return (double)(Double.doubleToLongBits(a)!=0?a:b); + return (double)(firstNonZero(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2291,7 +2490,7 @@ relativeError)); } static double MIN(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2312,7 +2511,7 @@ relativeError)); } static double min(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2331,7 +2530,7 @@ relativeError)); } static double MAX(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2352,7 +2551,7 @@ relativeError)); } static double max(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2429,7 +2628,7 @@ relativeError)); static double ADDReduce(double[] a, int idx) { double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2438,7 +2637,7 @@ relativeError)); static double ADDReduceAll(double[] a) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2456,7 +2655,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2469,20 +2668,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = ADD_IDENTITY; - assertEquals((double) (id + id), id, + assertEquals((double) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id + x), x); - assertEquals((double) (x + id), x); + assertEquals((double) (scalar_add(id, x)), x); + assertEquals((double) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id + x), x, + assertEquals((double) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x + id), x, + assertEquals((double) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2491,7 +2690,7 @@ relativeError)); double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2500,7 +2699,7 @@ relativeError)); static double ADDReduceAllMasked(double[] a, boolean[] mask) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2520,7 +2719,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2531,7 +2730,7 @@ relativeError)); static double MULReduce(double[] a, int idx) { double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2540,7 +2739,7 @@ relativeError)); static double MULReduceAll(double[] a) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2558,7 +2757,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2571,20 +2770,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MUL_IDENTITY; - assertEquals((double) (id * id), id, + assertEquals((double) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id * x), x); - assertEquals((double) (x * id), x); + assertEquals((double) (scalar_mul(id, x)), x); + assertEquals((double) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id * x), x, + assertEquals((double) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x * id), x, + assertEquals((double) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2593,7 +2792,7 @@ relativeError)); double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2602,7 +2801,7 @@ relativeError)); static double MULReduceAllMasked(double[] a, boolean[] mask) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2622,7 +2821,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2633,7 +2832,7 @@ relativeError)); static double MINReduce(double[] a, int idx) { double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2642,7 +2841,7 @@ relativeError)); static double MINReduceAll(double[] a) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2660,7 +2859,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2673,20 +2872,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MIN_IDENTITY; - assertEquals((double) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.min(id, x), x); - assertEquals((double) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2695,7 +2894,7 @@ relativeError)); double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2704,7 +2903,7 @@ relativeError)); static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2724,7 +2923,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2735,7 +2934,7 @@ relativeError)); static double MAXReduce(double[] a, int idx) { double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2744,7 +2943,7 @@ relativeError)); static double MAXReduceAll(double[] a) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2762,7 +2961,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2775,20 +2974,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MAX_IDENTITY; - assertEquals((double) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.max(id, x), x); - assertEquals((double) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2797,7 +2996,7 @@ relativeError)); double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2806,7 +3005,7 @@ relativeError)); static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2826,7 +3025,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3038,7 +3237,7 @@ relativeError)); } static boolean testIS_FINITE(double a) { - return Double.isFinite(a); + return isFinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3079,7 +3278,7 @@ relativeError)); } static boolean testIS_NAN(double a) { - return Double.isNaN(a); + return isNaN(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3120,7 +3319,7 @@ relativeError)); } static boolean testIS_INFINITE(double a) { - return Double.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3461,7 +3660,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3481,7 +3680,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3497,7 +3696,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (double)((long)b[i]))); } } } @@ -3517,7 +3716,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (double)((long)b[i])))); } } } @@ -3533,7 +3732,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3553,7 +3752,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3569,7 +3768,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (double)((long)b[i]))); } } } @@ -3589,7 +3788,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (double)((long)b[i])))); } } } @@ -4089,11 +4288,11 @@ relativeError)); } static double SIN(double a) { - return (double)(Math.sin((double)a)); + return (double)(scalar_sin(a)); } static double strictSIN(double a) { - return (double)(StrictMath.sin((double)a)); + return (double)(strict_scalar_sin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4112,11 +4311,11 @@ relativeError)); } static double EXP(double a) { - return (double)(Math.exp((double)a)); + return (double)(scalar_exp(a)); } static double strictEXP(double a) { - return (double)(StrictMath.exp((double)a)); + return (double)(strict_scalar_exp(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4135,11 +4334,11 @@ relativeError)); } static double LOG1P(double a) { - return (double)(Math.log1p((double)a)); + return (double)(scalar_log1p(a)); } static double strictLOG1P(double a) { - return (double)(StrictMath.log1p((double)a)); + return (double)(strict_scalar_log1p(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4158,11 +4357,11 @@ relativeError)); } static double LOG(double a) { - return (double)(Math.log((double)a)); + return (double)(scalar_log(a)); } static double strictLOG(double a) { - return (double)(StrictMath.log((double)a)); + return (double)(strict_scalar_log(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4181,11 +4380,11 @@ relativeError)); } static double LOG10(double a) { - return (double)(Math.log10((double)a)); + return (double)(scalar_log10(a)); } static double strictLOG10(double a) { - return (double)(StrictMath.log10((double)a)); + return (double)(strict_scalar_log10(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4204,11 +4403,11 @@ relativeError)); } static double EXPM1(double a) { - return (double)(Math.expm1((double)a)); + return (double)(scalar_expm1(a)); } static double strictEXPM1(double a) { - return (double)(StrictMath.expm1((double)a)); + return (double)(strict_scalar_expm1(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4227,11 +4426,11 @@ relativeError)); } static double COS(double a) { - return (double)(Math.cos((double)a)); + return (double)(scalar_cos(a)); } static double strictCOS(double a) { - return (double)(StrictMath.cos((double)a)); + return (double)(strict_scalar_cos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4250,11 +4449,11 @@ relativeError)); } static double TAN(double a) { - return (double)(Math.tan((double)a)); + return (double)(scalar_tan(a)); } static double strictTAN(double a) { - return (double)(StrictMath.tan((double)a)); + return (double)(strict_scalar_tan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4273,11 +4472,11 @@ relativeError)); } static double SINH(double a) { - return (double)(Math.sinh((double)a)); + return (double)(scalar_sinh(a)); } static double strictSINH(double a) { - return (double)(StrictMath.sinh((double)a)); + return (double)(strict_scalar_sinh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4296,11 +4495,11 @@ relativeError)); } static double COSH(double a) { - return (double)(Math.cosh((double)a)); + return (double)(scalar_cosh(a)); } static double strictCOSH(double a) { - return (double)(StrictMath.cosh((double)a)); + return (double)(strict_scalar_cosh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4319,11 +4518,11 @@ relativeError)); } static double TANH(double a) { - return (double)(Math.tanh((double)a)); + return (double)(scalar_tanh(a)); } static double strictTANH(double a) { - return (double)(StrictMath.tanh((double)a)); + return (double)(strict_scalar_tanh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4342,11 +4541,11 @@ relativeError)); } static double ASIN(double a) { - return (double)(Math.asin((double)a)); + return (double)(scalar_asin(a)); } static double strictASIN(double a) { - return (double)(StrictMath.asin((double)a)); + return (double)(strict_scalar_asin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4365,11 +4564,11 @@ relativeError)); } static double ACOS(double a) { - return (double)(Math.acos((double)a)); + return (double)(scalar_acos(a)); } static double strictACOS(double a) { - return (double)(StrictMath.acos((double)a)); + return (double)(strict_scalar_acos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4388,11 +4587,11 @@ relativeError)); } static double ATAN(double a) { - return (double)(Math.atan((double)a)); + return (double)(scalar_atan(a)); } static double strictATAN(double a) { - return (double)(StrictMath.atan((double)a)); + return (double)(strict_scalar_atan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4411,11 +4610,11 @@ relativeError)); } static double CBRT(double a) { - return (double)(Math.cbrt((double)a)); + return (double)(scalar_cbrt(a)); } static double strictCBRT(double a) { - return (double)(StrictMath.cbrt((double)a)); + return (double)(strict_scalar_cbrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4434,11 +4633,11 @@ relativeError)); } static double HYPOT(double a, double b) { - return (double)(Math.hypot((double)a, (double)b)); + return (double)(scalar_hypot(a, b)); } static double strictHYPOT(double a, double b) { - return (double)(StrictMath.hypot((double)a, (double)b)); + return (double)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4460,11 +4659,11 @@ relativeError)); static double POW(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictPOW(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4486,11 +4685,11 @@ relativeError)); static double pow(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictpow(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4512,11 +4711,11 @@ relativeError)); static double ATAN2(double a, double b) { - return (double)(Math.atan2((double)a, (double)b)); + return (double)(scalar_atan2(a, b)); } static double strictATAN2(double a, double b) { - return (double)(StrictMath.atan2((double)a, (double)b)); + return (double)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4568,11 +4767,11 @@ relativeError)); static double FMA(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } static double fma(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } @Test(dataProvider = "doubleTernaryOpProvider") @@ -4792,11 +4991,11 @@ relativeError)); } static double NEG(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } static double neg(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4848,11 +5047,11 @@ relativeError)); } static double ABS(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } static double abs(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4904,11 +5103,11 @@ relativeError)); } static double SQRT(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } static double sqrt(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -5121,7 +5320,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5137,7 +5336,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5196,7 +5395,7 @@ relativeError)); static long ADDReduceLong(double[] a, int idx) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5205,7 +5404,7 @@ relativeError)); static long ADDReduceAllLong(double[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((double)res, (double)ADDReduceLong(a, i)); } return res; @@ -5223,8 +5422,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5234,8 +5433,9 @@ relativeError)); static long ADDReduceLongMasked(double[] a, int idx, boolean[] mask) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5244,7 +5444,7 @@ relativeError)); static long ADDReduceAllLongMasked(double[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((double)res, (double)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5264,8 +5464,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java b/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java index c4dda942e83..2684ae2d0c6 100644 --- a/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleVectorMaxTests.java @@ -1590,6 +1590,205 @@ relativeError)); return Double.compare(a, (double) 0) != 0 ? a : b; } + + static double scalar_add(double a, double b) { + return (double)(a + b); + } + + static double scalar_sub(double a, double b) { + return (double)(a - b); + } + + static double scalar_mul(double a, double b) { + return (double)(a * b); + } + + static double scalar_min(double a, double b) { + return (double)(Math.min(a, b)); + } + + static double scalar_max(double a, double b) { + return (double)(Math.max(a, b)); + } + + static double scalar_div(double a, double b) { + return (double)(a / b); + } + + static double scalar_fma(double a, double b, double c) { + return (double)(Math.fma(a, b, c)); + } + + static double scalar_abs(double a) { + return (double)(Math.abs(a)); + } + + static double scalar_neg(double a) { + return ((double)-a); + } + + static double scalar_sin(double a) { + return (double)Math.sin((double)a); + } + + static double scalar_exp(double a) { + return (double)Math.exp((double)a); + } + + static double scalar_log1p(double a) { + return (double)Math.log1p((double)a); + } + + static double scalar_log(double a) { + return (double)Math.log((double)a); + } + + static double scalar_log10(double a) { + return (double)Math.log10((double)a); + } + + static double scalar_expm1(double a) { + return (double)Math.expm1((double)a); + } + + static double scalar_cos(double a) { + return (double)Math.cos((double)a); + } + + static double scalar_tan(double a) { + return (double)Math.tan((double)a); + } + + static double scalar_sinh(double a) { + return (double)Math.sinh((double)a); + } + + static double scalar_cosh(double a) { + return (double)Math.cosh((double)a); + } + + static double scalar_tanh(double a) { + return (double)Math.tanh((double)a); + } + + static double scalar_asin(double a) { + return (double)Math.asin((double)a); + } + + static double scalar_acos(double a) { + return (double)Math.acos((double)a); + } + + static double scalar_atan(double a) { + return (double)Math.atan((double)a); + } + + static double scalar_cbrt(double a) { + return (double)Math.cbrt((double)a); + } + + static double scalar_sqrt(double a) { + return (double)Math.sqrt((double)a); + } + + static double scalar_hypot(double a, double b) { + return (double)Math.hypot((double)a, (double)b); + } + + static double scalar_pow(double a, double b) { + return (double)Math.pow((double)a, (double)b); + } + + static double scalar_atan2(double a, double b) { + return (double)Math.atan2((double)a, (double)b); + } + + static double strict_scalar_sin(double a) { + return (double)StrictMath.sin((double)a); + } + + static double strict_scalar_exp(double a) { + return (double)StrictMath.exp((double)a); + } + + static double strict_scalar_log1p(double a) { + return (double)StrictMath.log1p((double)a); + } + + static double strict_scalar_log(double a) { + return (double)StrictMath.log((double)a); + } + + static double strict_scalar_log10(double a) { + return (double)StrictMath.log10((double)a); + } + + static double strict_scalar_expm1(double a) { + return (double)StrictMath.expm1((double)a); + } + + static double strict_scalar_cos(double a) { + return (double)StrictMath.cos((double)a); + } + + static double strict_scalar_tan(double a) { + return (double)StrictMath.tan((double)a); + } + + static double strict_scalar_sinh(double a) { + return (double)StrictMath.sinh((double)a); + } + + static double strict_scalar_cosh(double a) { + return (double)StrictMath.cosh((double)a); + } + + static double strict_scalar_tanh(double a) { + return (double)StrictMath.tanh((double)a); + } + + static double strict_scalar_asin(double a) { + return (double)StrictMath.asin((double)a); + } + + static double strict_scalar_acos(double a) { + return (double)StrictMath.acos((double)a); + } + + static double strict_scalar_atan(double a) { + return (double)StrictMath.atan((double)a); + } + + static double strict_scalar_cbrt(double a) { + return (double)StrictMath.cbrt((double)a); + } + + static double strict_scalar_sqrt(double a) { + return (double)StrictMath.sqrt((double)a); + } + + static double strict_scalar_hypot(double a, double b) { + return (double)StrictMath.hypot((double)a, (double)b); + } + + static double strict_scalar_pow(double a, double b) { + return (double)StrictMath.pow((double)a, (double)b); + } + + static double strict_scalar_atan2(double a, double b) { + return (double)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(double a) { + return Double.isNaN(a); + } + static boolean isFinite(double a) { + return Double.isFinite(a); + } + static boolean isInfinite(double a) { + return Double.isInfinite(a); + } + @Test static void smokeTest1() { DoubleVector three = DoubleVector.broadcast(SPECIES, (byte)-3); @@ -1683,7 +1882,7 @@ relativeError)); } static double ADD(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1704,7 +1903,7 @@ relativeError)); } static double add(double a, double b) { - return (double)(a + b); + return (double)(scalar_add(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1761,7 +1960,7 @@ relativeError)); } static double SUB(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1782,7 +1981,7 @@ relativeError)); } static double sub(double a, double b) { - return (double)(a - b); + return (double)(scalar_sub(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1839,7 +2038,7 @@ relativeError)); } static double MUL(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1860,7 +2059,7 @@ relativeError)); } static double mul(double a, double b) { - return (double)(a * b); + return (double)(scalar_mul(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1917,7 +2116,7 @@ relativeError)); } static double DIV(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1938,7 +2137,7 @@ relativeError)); } static double div(double a, double b) { - return (double)(a / b); + return (double)(scalar_div(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -1995,7 +2194,7 @@ relativeError)); } static double FIRST_NONZERO(double a, double b) { - return (double)(Double.doubleToLongBits(a)!=0?a:b); + return (double)(firstNonZero(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2297,7 +2496,7 @@ relativeError)); } static double MIN(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2318,7 +2517,7 @@ relativeError)); } static double min(double a, double b) { - return (double)(Math.min(a, b)); + return (double)(scalar_min(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2337,7 +2536,7 @@ relativeError)); } static double MAX(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2358,7 +2557,7 @@ relativeError)); } static double max(double a, double b) { - return (double)(Math.max(a, b)); + return (double)(scalar_max(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -2435,7 +2634,7 @@ relativeError)); static double ADDReduce(double[] a, int idx) { double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2444,7 +2643,7 @@ relativeError)); static double ADDReduceAll(double[] a) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2462,7 +2661,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2475,20 +2674,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = ADD_IDENTITY; - assertEquals((double) (id + id), id, + assertEquals((double) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id + x), x); - assertEquals((double) (x + id), x); + assertEquals((double) (scalar_add(id, x)), x); + assertEquals((double) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id + x), x, + assertEquals((double) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x + id), x, + assertEquals((double) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2497,7 +2696,7 @@ relativeError)); double res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2506,7 +2705,7 @@ relativeError)); static double ADDReduceAllMasked(double[] a, boolean[] mask) { double res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2526,7 +2725,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2537,7 +2736,7 @@ relativeError)); static double MULReduce(double[] a, int idx) { double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2546,7 +2745,7 @@ relativeError)); static double MULReduceAll(double[] a) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2564,7 +2763,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2577,20 +2776,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MUL_IDENTITY; - assertEquals((double) (id * id), id, + assertEquals((double) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) (id * x), x); - assertEquals((double) (x * id), x); + assertEquals((double) (scalar_mul(id, x)), x); + assertEquals((double) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((double) (id * x), x, + assertEquals((double) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((double) (x * id), x, + assertEquals((double) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2599,7 +2798,7 @@ relativeError)); double res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2608,7 +2807,7 @@ relativeError)); static double MULReduceAllMasked(double[] a, boolean[] mask) { double res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2628,7 +2827,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2639,7 +2838,7 @@ relativeError)); static double MINReduce(double[] a, int idx) { double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2648,7 +2847,7 @@ relativeError)); static double MINReduceAll(double[] a) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2666,7 +2865,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2679,20 +2878,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MIN_IDENTITY; - assertEquals((double) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.min(id, x), x); - assertEquals((double) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2701,7 +2900,7 @@ relativeError)); double res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2710,7 +2909,7 @@ relativeError)); static double MINReduceAllMasked(double[] a, boolean[] mask) { double res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2730,7 +2929,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (double) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2741,7 +2940,7 @@ relativeError)); static double MAXReduce(double[] a, int idx) { double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2750,7 +2949,7 @@ relativeError)); static double MAXReduceAll(double[] a) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2768,7 +2967,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2781,20 +2980,20 @@ relativeError)); double[] a = fa.apply(SPECIES.length()); double id = MAX_IDENTITY; - assertEquals((double) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); double x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((double) Math.max(id, x), x); - assertEquals((double) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((double) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((double) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2803,7 +3002,7 @@ relativeError)); double res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (double) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2812,7 +3011,7 @@ relativeError)); static double MAXReduceAllMasked(double[] a, boolean[] mask) { double res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (double) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2832,7 +3031,7 @@ relativeError)); DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); double v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (double) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3044,7 +3243,7 @@ relativeError)); } static boolean testIS_FINITE(double a) { - return Double.isFinite(a); + return isFinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3085,7 +3284,7 @@ relativeError)); } static boolean testIS_NAN(double a) { - return Double.isNaN(a); + return isNaN(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3126,7 +3325,7 @@ relativeError)); } static boolean testIS_INFINITE(double a) { - return Double.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "doubleTestOpProvider") @@ -3467,7 +3666,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3487,7 +3686,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3503,7 +3702,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (double)((long)b[i]))); } } } @@ -3523,7 +3722,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (double)((long)b[i])))); } } } @@ -3539,7 +3738,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3559,7 +3758,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3575,7 +3774,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (double)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (double)((long)b[i]))); } } } @@ -3595,7 +3794,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (double)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (double)((long)b[i])))); } } } @@ -4095,11 +4294,11 @@ relativeError)); } static double SIN(double a) { - return (double)(Math.sin((double)a)); + return (double)(scalar_sin(a)); } static double strictSIN(double a) { - return (double)(StrictMath.sin((double)a)); + return (double)(strict_scalar_sin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4118,11 +4317,11 @@ relativeError)); } static double EXP(double a) { - return (double)(Math.exp((double)a)); + return (double)(scalar_exp(a)); } static double strictEXP(double a) { - return (double)(StrictMath.exp((double)a)); + return (double)(strict_scalar_exp(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4141,11 +4340,11 @@ relativeError)); } static double LOG1P(double a) { - return (double)(Math.log1p((double)a)); + return (double)(scalar_log1p(a)); } static double strictLOG1P(double a) { - return (double)(StrictMath.log1p((double)a)); + return (double)(strict_scalar_log1p(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4164,11 +4363,11 @@ relativeError)); } static double LOG(double a) { - return (double)(Math.log((double)a)); + return (double)(scalar_log(a)); } static double strictLOG(double a) { - return (double)(StrictMath.log((double)a)); + return (double)(strict_scalar_log(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4187,11 +4386,11 @@ relativeError)); } static double LOG10(double a) { - return (double)(Math.log10((double)a)); + return (double)(scalar_log10(a)); } static double strictLOG10(double a) { - return (double)(StrictMath.log10((double)a)); + return (double)(strict_scalar_log10(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4210,11 +4409,11 @@ relativeError)); } static double EXPM1(double a) { - return (double)(Math.expm1((double)a)); + return (double)(scalar_expm1(a)); } static double strictEXPM1(double a) { - return (double)(StrictMath.expm1((double)a)); + return (double)(strict_scalar_expm1(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4233,11 +4432,11 @@ relativeError)); } static double COS(double a) { - return (double)(Math.cos((double)a)); + return (double)(scalar_cos(a)); } static double strictCOS(double a) { - return (double)(StrictMath.cos((double)a)); + return (double)(strict_scalar_cos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4256,11 +4455,11 @@ relativeError)); } static double TAN(double a) { - return (double)(Math.tan((double)a)); + return (double)(scalar_tan(a)); } static double strictTAN(double a) { - return (double)(StrictMath.tan((double)a)); + return (double)(strict_scalar_tan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4279,11 +4478,11 @@ relativeError)); } static double SINH(double a) { - return (double)(Math.sinh((double)a)); + return (double)(scalar_sinh(a)); } static double strictSINH(double a) { - return (double)(StrictMath.sinh((double)a)); + return (double)(strict_scalar_sinh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4302,11 +4501,11 @@ relativeError)); } static double COSH(double a) { - return (double)(Math.cosh((double)a)); + return (double)(scalar_cosh(a)); } static double strictCOSH(double a) { - return (double)(StrictMath.cosh((double)a)); + return (double)(strict_scalar_cosh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4325,11 +4524,11 @@ relativeError)); } static double TANH(double a) { - return (double)(Math.tanh((double)a)); + return (double)(scalar_tanh(a)); } static double strictTANH(double a) { - return (double)(StrictMath.tanh((double)a)); + return (double)(strict_scalar_tanh(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4348,11 +4547,11 @@ relativeError)); } static double ASIN(double a) { - return (double)(Math.asin((double)a)); + return (double)(scalar_asin(a)); } static double strictASIN(double a) { - return (double)(StrictMath.asin((double)a)); + return (double)(strict_scalar_asin(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4371,11 +4570,11 @@ relativeError)); } static double ACOS(double a) { - return (double)(Math.acos((double)a)); + return (double)(scalar_acos(a)); } static double strictACOS(double a) { - return (double)(StrictMath.acos((double)a)); + return (double)(strict_scalar_acos(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4394,11 +4593,11 @@ relativeError)); } static double ATAN(double a) { - return (double)(Math.atan((double)a)); + return (double)(scalar_atan(a)); } static double strictATAN(double a) { - return (double)(StrictMath.atan((double)a)); + return (double)(strict_scalar_atan(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4417,11 +4616,11 @@ relativeError)); } static double CBRT(double a) { - return (double)(Math.cbrt((double)a)); + return (double)(scalar_cbrt(a)); } static double strictCBRT(double a) { - return (double)(StrictMath.cbrt((double)a)); + return (double)(strict_scalar_cbrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4440,11 +4639,11 @@ relativeError)); } static double HYPOT(double a, double b) { - return (double)(Math.hypot((double)a, (double)b)); + return (double)(scalar_hypot(a, b)); } static double strictHYPOT(double a, double b) { - return (double)(StrictMath.hypot((double)a, (double)b)); + return (double)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4466,11 +4665,11 @@ relativeError)); static double POW(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictPOW(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4492,11 +4691,11 @@ relativeError)); static double pow(double a, double b) { - return (double)(Math.pow((double)a, (double)b)); + return (double)(scalar_pow(a, b)); } static double strictpow(double a, double b) { - return (double)(StrictMath.pow((double)a, (double)b)); + return (double)(strict_scalar_pow(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4518,11 +4717,11 @@ relativeError)); static double ATAN2(double a, double b) { - return (double)(Math.atan2((double)a, (double)b)); + return (double)(scalar_atan2(a, b)); } static double strictATAN2(double a, double b) { - return (double)(StrictMath.atan2((double)a, (double)b)); + return (double)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "doubleBinaryOpProvider") @@ -4574,11 +4773,11 @@ relativeError)); static double FMA(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } static double fma(double a, double b, double c) { - return (double)(Math.fma(a, b, c)); + return (double)(scalar_fma(a, b, c)); } @Test(dataProvider = "doubleTernaryOpProvider") @@ -4798,11 +4997,11 @@ relativeError)); } static double NEG(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } static double neg(double a) { - return (double)(-((double)a)); + return (double)(scalar_neg((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4854,11 +5053,11 @@ relativeError)); } static double ABS(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } static double abs(double a) { - return (double)(Math.abs((double)a)); + return (double)(scalar_abs((double)a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -4910,11 +5109,11 @@ relativeError)); } static double SQRT(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } static double sqrt(double a) { - return (double)(Math.sqrt((double)a)); + return (double)(scalar_sqrt(a)); } @Test(dataProvider = "doubleUnaryOpProvider") @@ -5127,7 +5326,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5143,7 +5342,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5202,7 +5401,7 @@ relativeError)); static long ADDReduceLong(double[] a, int idx) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5211,7 +5410,7 @@ relativeError)); static long ADDReduceAllLong(double[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((double)res, (double)ADDReduceLong(a, i)); } return res; @@ -5229,8 +5428,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5240,8 +5439,9 @@ relativeError)); static long ADDReduceLongMasked(double[] a, int idx, boolean[] mask) { double res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5250,7 +5450,7 @@ relativeError)); static long ADDReduceAllLongMasked(double[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((double)res, (double)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5270,8 +5470,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((double)ra, (double)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/FloatVector128Tests.java b/test/jdk/jdk/incubator/vector/FloatVector128Tests.java index 51e6365b01b..151ea17a886 100644 --- a/test/jdk/jdk/incubator/vector/FloatVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/FloatVector128Tests.java @@ -1601,6 +1601,205 @@ relativeError)); return Float.compare(a, (float) 0) != 0 ? a : b; } + + static float scalar_add(float a, float b) { + return (float)(a + b); + } + + static float scalar_sub(float a, float b) { + return (float)(a - b); + } + + static float scalar_mul(float a, float b) { + return (float)(a * b); + } + + static float scalar_min(float a, float b) { + return (float)(Math.min(a, b)); + } + + static float scalar_max(float a, float b) { + return (float)(Math.max(a, b)); + } + + static float scalar_div(float a, float b) { + return (float)(a / b); + } + + static float scalar_fma(float a, float b, float c) { + return (float)(Math.fma(a, b, c)); + } + + static float scalar_abs(float a) { + return (float)(Math.abs(a)); + } + + static float scalar_neg(float a) { + return ((float)-a); + } + + static float scalar_sin(float a) { + return (float)Math.sin((double)a); + } + + static float scalar_exp(float a) { + return (float)Math.exp((double)a); + } + + static float scalar_log1p(float a) { + return (float)Math.log1p((double)a); + } + + static float scalar_log(float a) { + return (float)Math.log((double)a); + } + + static float scalar_log10(float a) { + return (float)Math.log10((double)a); + } + + static float scalar_expm1(float a) { + return (float)Math.expm1((double)a); + } + + static float scalar_cos(float a) { + return (float)Math.cos((double)a); + } + + static float scalar_tan(float a) { + return (float)Math.tan((double)a); + } + + static float scalar_sinh(float a) { + return (float)Math.sinh((double)a); + } + + static float scalar_cosh(float a) { + return (float)Math.cosh((double)a); + } + + static float scalar_tanh(float a) { + return (float)Math.tanh((double)a); + } + + static float scalar_asin(float a) { + return (float)Math.asin((double)a); + } + + static float scalar_acos(float a) { + return (float)Math.acos((double)a); + } + + static float scalar_atan(float a) { + return (float)Math.atan((double)a); + } + + static float scalar_cbrt(float a) { + return (float)Math.cbrt((double)a); + } + + static float scalar_sqrt(float a) { + return (float)Math.sqrt((double)a); + } + + static float scalar_hypot(float a, float b) { + return (float)Math.hypot((double)a, (double)b); + } + + static float scalar_pow(float a, float b) { + return (float)Math.pow((double)a, (double)b); + } + + static float scalar_atan2(float a, float b) { + return (float)Math.atan2((double)a, (double)b); + } + + static float strict_scalar_sin(float a) { + return (float)StrictMath.sin((double)a); + } + + static float strict_scalar_exp(float a) { + return (float)StrictMath.exp((double)a); + } + + static float strict_scalar_log1p(float a) { + return (float)StrictMath.log1p((double)a); + } + + static float strict_scalar_log(float a) { + return (float)StrictMath.log((double)a); + } + + static float strict_scalar_log10(float a) { + return (float)StrictMath.log10((double)a); + } + + static float strict_scalar_expm1(float a) { + return (float)StrictMath.expm1((double)a); + } + + static float strict_scalar_cos(float a) { + return (float)StrictMath.cos((double)a); + } + + static float strict_scalar_tan(float a) { + return (float)StrictMath.tan((double)a); + } + + static float strict_scalar_sinh(float a) { + return (float)StrictMath.sinh((double)a); + } + + static float strict_scalar_cosh(float a) { + return (float)StrictMath.cosh((double)a); + } + + static float strict_scalar_tanh(float a) { + return (float)StrictMath.tanh((double)a); + } + + static float strict_scalar_asin(float a) { + return (float)StrictMath.asin((double)a); + } + + static float strict_scalar_acos(float a) { + return (float)StrictMath.acos((double)a); + } + + static float strict_scalar_atan(float a) { + return (float)StrictMath.atan((double)a); + } + + static float strict_scalar_cbrt(float a) { + return (float)StrictMath.cbrt((double)a); + } + + static float strict_scalar_sqrt(float a) { + return (float)StrictMath.sqrt((double)a); + } + + static float strict_scalar_hypot(float a, float b) { + return (float)StrictMath.hypot((double)a, (double)b); + } + + static float strict_scalar_pow(float a, float b) { + return (float)StrictMath.pow((double)a, (double)b); + } + + static float strict_scalar_atan2(float a, float b) { + return (float)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(float a) { + return Float.isNaN(a); + } + static boolean isFinite(float a) { + return Float.isFinite(a); + } + static boolean isInfinite(float a) { + return Float.isInfinite(a); + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -1694,7 +1893,7 @@ relativeError)); } static float ADD(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1715,7 +1914,7 @@ relativeError)); } static float add(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1772,7 +1971,7 @@ relativeError)); } static float SUB(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1793,7 +1992,7 @@ relativeError)); } static float sub(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1850,7 +2049,7 @@ relativeError)); } static float MUL(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1871,7 +2070,7 @@ relativeError)); } static float mul(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1928,7 +2127,7 @@ relativeError)); } static float DIV(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1949,7 +2148,7 @@ relativeError)); } static float div(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2006,7 +2205,7 @@ relativeError)); } static float FIRST_NONZERO(float a, float b) { - return (float)(Double.doubleToLongBits(a)!=0?a:b); + return (float)(firstNonZero(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2308,7 +2507,7 @@ relativeError)); } static float MIN(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2329,7 +2528,7 @@ relativeError)); } static float min(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2348,7 +2547,7 @@ relativeError)); } static float MAX(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2369,7 +2568,7 @@ relativeError)); } static float max(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2446,7 +2645,7 @@ relativeError)); static float ADDReduce(float[] a, int idx) { float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2455,7 +2654,7 @@ relativeError)); static float ADDReduceAll(float[] a) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2473,7 +2672,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2486,20 +2685,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = ADD_IDENTITY; - assertEquals((float) (id + id), id, + assertEquals((float) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id + x), x); - assertEquals((float) (x + id), x); + assertEquals((float) (scalar_add(id, x)), x); + assertEquals((float) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id + x), x, + assertEquals((float) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x + id), x, + assertEquals((float) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2508,7 +2707,7 @@ relativeError)); float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2517,7 +2716,7 @@ relativeError)); static float ADDReduceAllMasked(float[] a, boolean[] mask) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2537,7 +2736,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2548,7 +2747,7 @@ relativeError)); static float MULReduce(float[] a, int idx) { float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2557,7 +2756,7 @@ relativeError)); static float MULReduceAll(float[] a) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2575,7 +2774,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2588,20 +2787,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MUL_IDENTITY; - assertEquals((float) (id * id), id, + assertEquals((float) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id * x), x); - assertEquals((float) (x * id), x); + assertEquals((float) (scalar_mul(id, x)), x); + assertEquals((float) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id * x), x, + assertEquals((float) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x * id), x, + assertEquals((float) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2610,7 +2809,7 @@ relativeError)); float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2619,7 +2818,7 @@ relativeError)); static float MULReduceAllMasked(float[] a, boolean[] mask) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2639,7 +2838,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2650,7 +2849,7 @@ relativeError)); static float MINReduce(float[] a, int idx) { float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2659,7 +2858,7 @@ relativeError)); static float MINReduceAll(float[] a) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2677,7 +2876,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2690,20 +2889,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MIN_IDENTITY; - assertEquals((float) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.min(id, x), x); - assertEquals((float) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2712,7 +2911,7 @@ relativeError)); float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2721,7 +2920,7 @@ relativeError)); static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2741,7 +2940,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2752,7 +2951,7 @@ relativeError)); static float MAXReduce(float[] a, int idx) { float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2761,7 +2960,7 @@ relativeError)); static float MAXReduceAll(float[] a) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2779,7 +2978,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2792,20 +2991,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MAX_IDENTITY; - assertEquals((float) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.max(id, x), x); - assertEquals((float) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2814,7 +3013,7 @@ relativeError)); float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2823,7 +3022,7 @@ relativeError)); static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2843,7 +3042,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3055,7 +3254,7 @@ relativeError)); } static boolean testIS_FINITE(float a) { - return Float.isFinite(a); + return isFinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3096,7 +3295,7 @@ relativeError)); } static boolean testIS_NAN(float a) { - return Float.isNaN(a); + return isNaN(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3137,7 +3336,7 @@ relativeError)); } static boolean testIS_INFINITE(float a) { - return Float.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3478,7 +3677,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3498,7 +3697,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3514,7 +3713,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (float)((long)b[i]))); } } } @@ -3534,7 +3733,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (float)((long)b[i])))); } } } @@ -3550,7 +3749,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3570,7 +3769,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3586,7 +3785,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (float)((long)b[i]))); } } } @@ -3606,7 +3805,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (float)((long)b[i])))); } } } @@ -4106,11 +4305,11 @@ relativeError)); } static float SIN(float a) { - return (float)(Math.sin((double)a)); + return (float)(scalar_sin(a)); } static float strictSIN(float a) { - return (float)(StrictMath.sin((double)a)); + return (float)(strict_scalar_sin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4129,11 +4328,11 @@ relativeError)); } static float EXP(float a) { - return (float)(Math.exp((double)a)); + return (float)(scalar_exp(a)); } static float strictEXP(float a) { - return (float)(StrictMath.exp((double)a)); + return (float)(strict_scalar_exp(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4152,11 +4351,11 @@ relativeError)); } static float LOG1P(float a) { - return (float)(Math.log1p((double)a)); + return (float)(scalar_log1p(a)); } static float strictLOG1P(float a) { - return (float)(StrictMath.log1p((double)a)); + return (float)(strict_scalar_log1p(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4175,11 +4374,11 @@ relativeError)); } static float LOG(float a) { - return (float)(Math.log((double)a)); + return (float)(scalar_log(a)); } static float strictLOG(float a) { - return (float)(StrictMath.log((double)a)); + return (float)(strict_scalar_log(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4198,11 +4397,11 @@ relativeError)); } static float LOG10(float a) { - return (float)(Math.log10((double)a)); + return (float)(scalar_log10(a)); } static float strictLOG10(float a) { - return (float)(StrictMath.log10((double)a)); + return (float)(strict_scalar_log10(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4221,11 +4420,11 @@ relativeError)); } static float EXPM1(float a) { - return (float)(Math.expm1((double)a)); + return (float)(scalar_expm1(a)); } static float strictEXPM1(float a) { - return (float)(StrictMath.expm1((double)a)); + return (float)(strict_scalar_expm1(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4244,11 +4443,11 @@ relativeError)); } static float COS(float a) { - return (float)(Math.cos((double)a)); + return (float)(scalar_cos(a)); } static float strictCOS(float a) { - return (float)(StrictMath.cos((double)a)); + return (float)(strict_scalar_cos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4267,11 +4466,11 @@ relativeError)); } static float TAN(float a) { - return (float)(Math.tan((double)a)); + return (float)(scalar_tan(a)); } static float strictTAN(float a) { - return (float)(StrictMath.tan((double)a)); + return (float)(strict_scalar_tan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4290,11 +4489,11 @@ relativeError)); } static float SINH(float a) { - return (float)(Math.sinh((double)a)); + return (float)(scalar_sinh(a)); } static float strictSINH(float a) { - return (float)(StrictMath.sinh((double)a)); + return (float)(strict_scalar_sinh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4313,11 +4512,11 @@ relativeError)); } static float COSH(float a) { - return (float)(Math.cosh((double)a)); + return (float)(scalar_cosh(a)); } static float strictCOSH(float a) { - return (float)(StrictMath.cosh((double)a)); + return (float)(strict_scalar_cosh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4336,11 +4535,11 @@ relativeError)); } static float TANH(float a) { - return (float)(Math.tanh((double)a)); + return (float)(scalar_tanh(a)); } static float strictTANH(float a) { - return (float)(StrictMath.tanh((double)a)); + return (float)(strict_scalar_tanh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4359,11 +4558,11 @@ relativeError)); } static float ASIN(float a) { - return (float)(Math.asin((double)a)); + return (float)(scalar_asin(a)); } static float strictASIN(float a) { - return (float)(StrictMath.asin((double)a)); + return (float)(strict_scalar_asin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4382,11 +4581,11 @@ relativeError)); } static float ACOS(float a) { - return (float)(Math.acos((double)a)); + return (float)(scalar_acos(a)); } static float strictACOS(float a) { - return (float)(StrictMath.acos((double)a)); + return (float)(strict_scalar_acos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4405,11 +4604,11 @@ relativeError)); } static float ATAN(float a) { - return (float)(Math.atan((double)a)); + return (float)(scalar_atan(a)); } static float strictATAN(float a) { - return (float)(StrictMath.atan((double)a)); + return (float)(strict_scalar_atan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4428,11 +4627,11 @@ relativeError)); } static float CBRT(float a) { - return (float)(Math.cbrt((double)a)); + return (float)(scalar_cbrt(a)); } static float strictCBRT(float a) { - return (float)(StrictMath.cbrt((double)a)); + return (float)(strict_scalar_cbrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4451,11 +4650,11 @@ relativeError)); } static float HYPOT(float a, float b) { - return (float)(Math.hypot((double)a, (double)b)); + return (float)(scalar_hypot(a, b)); } static float strictHYPOT(float a, float b) { - return (float)(StrictMath.hypot((double)a, (double)b)); + return (float)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4477,11 +4676,11 @@ relativeError)); static float POW(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictPOW(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4503,11 +4702,11 @@ relativeError)); static float pow(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictpow(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4529,11 +4728,11 @@ relativeError)); static float ATAN2(float a, float b) { - return (float)(Math.atan2((double)a, (double)b)); + return (float)(scalar_atan2(a, b)); } static float strictATAN2(float a, float b) { - return (float)(StrictMath.atan2((double)a, (double)b)); + return (float)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4585,11 +4784,11 @@ relativeError)); static float FMA(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } static float fma(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } @Test(dataProvider = "floatTernaryOpProvider") @@ -4767,11 +4966,11 @@ relativeError)); } static float NEG(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } static float neg(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4823,11 +5022,11 @@ relativeError)); } static float ABS(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } static float abs(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4879,11 +5078,11 @@ relativeError)); } static float SQRT(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } static float sqrt(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -5096,7 +5295,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5112,7 +5311,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5181,7 +5380,7 @@ relativeError)); static long ADDReduceLong(float[] a, int idx) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5190,7 +5389,7 @@ relativeError)); static long ADDReduceAllLong(float[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((float)res, (float)ADDReduceLong(a, i)); } return res; @@ -5208,8 +5407,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5219,8 +5418,9 @@ relativeError)); static long ADDReduceLongMasked(float[] a, int idx, boolean[] mask) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5229,7 +5429,7 @@ relativeError)); static long ADDReduceAllLongMasked(float[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((float)res, (float)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5249,8 +5449,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/FloatVector256Tests.java b/test/jdk/jdk/incubator/vector/FloatVector256Tests.java index b7d16ecc7f7..5315b69a5b6 100644 --- a/test/jdk/jdk/incubator/vector/FloatVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/FloatVector256Tests.java @@ -1601,6 +1601,205 @@ relativeError)); return Float.compare(a, (float) 0) != 0 ? a : b; } + + static float scalar_add(float a, float b) { + return (float)(a + b); + } + + static float scalar_sub(float a, float b) { + return (float)(a - b); + } + + static float scalar_mul(float a, float b) { + return (float)(a * b); + } + + static float scalar_min(float a, float b) { + return (float)(Math.min(a, b)); + } + + static float scalar_max(float a, float b) { + return (float)(Math.max(a, b)); + } + + static float scalar_div(float a, float b) { + return (float)(a / b); + } + + static float scalar_fma(float a, float b, float c) { + return (float)(Math.fma(a, b, c)); + } + + static float scalar_abs(float a) { + return (float)(Math.abs(a)); + } + + static float scalar_neg(float a) { + return ((float)-a); + } + + static float scalar_sin(float a) { + return (float)Math.sin((double)a); + } + + static float scalar_exp(float a) { + return (float)Math.exp((double)a); + } + + static float scalar_log1p(float a) { + return (float)Math.log1p((double)a); + } + + static float scalar_log(float a) { + return (float)Math.log((double)a); + } + + static float scalar_log10(float a) { + return (float)Math.log10((double)a); + } + + static float scalar_expm1(float a) { + return (float)Math.expm1((double)a); + } + + static float scalar_cos(float a) { + return (float)Math.cos((double)a); + } + + static float scalar_tan(float a) { + return (float)Math.tan((double)a); + } + + static float scalar_sinh(float a) { + return (float)Math.sinh((double)a); + } + + static float scalar_cosh(float a) { + return (float)Math.cosh((double)a); + } + + static float scalar_tanh(float a) { + return (float)Math.tanh((double)a); + } + + static float scalar_asin(float a) { + return (float)Math.asin((double)a); + } + + static float scalar_acos(float a) { + return (float)Math.acos((double)a); + } + + static float scalar_atan(float a) { + return (float)Math.atan((double)a); + } + + static float scalar_cbrt(float a) { + return (float)Math.cbrt((double)a); + } + + static float scalar_sqrt(float a) { + return (float)Math.sqrt((double)a); + } + + static float scalar_hypot(float a, float b) { + return (float)Math.hypot((double)a, (double)b); + } + + static float scalar_pow(float a, float b) { + return (float)Math.pow((double)a, (double)b); + } + + static float scalar_atan2(float a, float b) { + return (float)Math.atan2((double)a, (double)b); + } + + static float strict_scalar_sin(float a) { + return (float)StrictMath.sin((double)a); + } + + static float strict_scalar_exp(float a) { + return (float)StrictMath.exp((double)a); + } + + static float strict_scalar_log1p(float a) { + return (float)StrictMath.log1p((double)a); + } + + static float strict_scalar_log(float a) { + return (float)StrictMath.log((double)a); + } + + static float strict_scalar_log10(float a) { + return (float)StrictMath.log10((double)a); + } + + static float strict_scalar_expm1(float a) { + return (float)StrictMath.expm1((double)a); + } + + static float strict_scalar_cos(float a) { + return (float)StrictMath.cos((double)a); + } + + static float strict_scalar_tan(float a) { + return (float)StrictMath.tan((double)a); + } + + static float strict_scalar_sinh(float a) { + return (float)StrictMath.sinh((double)a); + } + + static float strict_scalar_cosh(float a) { + return (float)StrictMath.cosh((double)a); + } + + static float strict_scalar_tanh(float a) { + return (float)StrictMath.tanh((double)a); + } + + static float strict_scalar_asin(float a) { + return (float)StrictMath.asin((double)a); + } + + static float strict_scalar_acos(float a) { + return (float)StrictMath.acos((double)a); + } + + static float strict_scalar_atan(float a) { + return (float)StrictMath.atan((double)a); + } + + static float strict_scalar_cbrt(float a) { + return (float)StrictMath.cbrt((double)a); + } + + static float strict_scalar_sqrt(float a) { + return (float)StrictMath.sqrt((double)a); + } + + static float strict_scalar_hypot(float a, float b) { + return (float)StrictMath.hypot((double)a, (double)b); + } + + static float strict_scalar_pow(float a, float b) { + return (float)StrictMath.pow((double)a, (double)b); + } + + static float strict_scalar_atan2(float a, float b) { + return (float)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(float a) { + return Float.isNaN(a); + } + static boolean isFinite(float a) { + return Float.isFinite(a); + } + static boolean isInfinite(float a) { + return Float.isInfinite(a); + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -1694,7 +1893,7 @@ relativeError)); } static float ADD(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1715,7 +1914,7 @@ relativeError)); } static float add(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1772,7 +1971,7 @@ relativeError)); } static float SUB(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1793,7 +1992,7 @@ relativeError)); } static float sub(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1850,7 +2049,7 @@ relativeError)); } static float MUL(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1871,7 +2070,7 @@ relativeError)); } static float mul(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1928,7 +2127,7 @@ relativeError)); } static float DIV(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1949,7 +2148,7 @@ relativeError)); } static float div(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2006,7 +2205,7 @@ relativeError)); } static float FIRST_NONZERO(float a, float b) { - return (float)(Double.doubleToLongBits(a)!=0?a:b); + return (float)(firstNonZero(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2308,7 +2507,7 @@ relativeError)); } static float MIN(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2329,7 +2528,7 @@ relativeError)); } static float min(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2348,7 +2547,7 @@ relativeError)); } static float MAX(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2369,7 +2568,7 @@ relativeError)); } static float max(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2446,7 +2645,7 @@ relativeError)); static float ADDReduce(float[] a, int idx) { float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2455,7 +2654,7 @@ relativeError)); static float ADDReduceAll(float[] a) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2473,7 +2672,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2486,20 +2685,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = ADD_IDENTITY; - assertEquals((float) (id + id), id, + assertEquals((float) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id + x), x); - assertEquals((float) (x + id), x); + assertEquals((float) (scalar_add(id, x)), x); + assertEquals((float) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id + x), x, + assertEquals((float) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x + id), x, + assertEquals((float) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2508,7 +2707,7 @@ relativeError)); float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2517,7 +2716,7 @@ relativeError)); static float ADDReduceAllMasked(float[] a, boolean[] mask) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2537,7 +2736,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2548,7 +2747,7 @@ relativeError)); static float MULReduce(float[] a, int idx) { float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2557,7 +2756,7 @@ relativeError)); static float MULReduceAll(float[] a) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2575,7 +2774,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2588,20 +2787,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MUL_IDENTITY; - assertEquals((float) (id * id), id, + assertEquals((float) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id * x), x); - assertEquals((float) (x * id), x); + assertEquals((float) (scalar_mul(id, x)), x); + assertEquals((float) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id * x), x, + assertEquals((float) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x * id), x, + assertEquals((float) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2610,7 +2809,7 @@ relativeError)); float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2619,7 +2818,7 @@ relativeError)); static float MULReduceAllMasked(float[] a, boolean[] mask) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2639,7 +2838,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2650,7 +2849,7 @@ relativeError)); static float MINReduce(float[] a, int idx) { float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2659,7 +2858,7 @@ relativeError)); static float MINReduceAll(float[] a) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2677,7 +2876,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2690,20 +2889,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MIN_IDENTITY; - assertEquals((float) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.min(id, x), x); - assertEquals((float) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2712,7 +2911,7 @@ relativeError)); float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2721,7 +2920,7 @@ relativeError)); static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2741,7 +2940,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2752,7 +2951,7 @@ relativeError)); static float MAXReduce(float[] a, int idx) { float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2761,7 +2960,7 @@ relativeError)); static float MAXReduceAll(float[] a) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2779,7 +2978,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2792,20 +2991,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MAX_IDENTITY; - assertEquals((float) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.max(id, x), x); - assertEquals((float) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2814,7 +3013,7 @@ relativeError)); float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2823,7 +3022,7 @@ relativeError)); static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2843,7 +3042,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3055,7 +3254,7 @@ relativeError)); } static boolean testIS_FINITE(float a) { - return Float.isFinite(a); + return isFinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3096,7 +3295,7 @@ relativeError)); } static boolean testIS_NAN(float a) { - return Float.isNaN(a); + return isNaN(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3137,7 +3336,7 @@ relativeError)); } static boolean testIS_INFINITE(float a) { - return Float.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3478,7 +3677,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3498,7 +3697,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3514,7 +3713,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (float)((long)b[i]))); } } } @@ -3534,7 +3733,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (float)((long)b[i])))); } } } @@ -3550,7 +3749,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3570,7 +3769,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3586,7 +3785,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (float)((long)b[i]))); } } } @@ -3606,7 +3805,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (float)((long)b[i])))); } } } @@ -4106,11 +4305,11 @@ relativeError)); } static float SIN(float a) { - return (float)(Math.sin((double)a)); + return (float)(scalar_sin(a)); } static float strictSIN(float a) { - return (float)(StrictMath.sin((double)a)); + return (float)(strict_scalar_sin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4129,11 +4328,11 @@ relativeError)); } static float EXP(float a) { - return (float)(Math.exp((double)a)); + return (float)(scalar_exp(a)); } static float strictEXP(float a) { - return (float)(StrictMath.exp((double)a)); + return (float)(strict_scalar_exp(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4152,11 +4351,11 @@ relativeError)); } static float LOG1P(float a) { - return (float)(Math.log1p((double)a)); + return (float)(scalar_log1p(a)); } static float strictLOG1P(float a) { - return (float)(StrictMath.log1p((double)a)); + return (float)(strict_scalar_log1p(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4175,11 +4374,11 @@ relativeError)); } static float LOG(float a) { - return (float)(Math.log((double)a)); + return (float)(scalar_log(a)); } static float strictLOG(float a) { - return (float)(StrictMath.log((double)a)); + return (float)(strict_scalar_log(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4198,11 +4397,11 @@ relativeError)); } static float LOG10(float a) { - return (float)(Math.log10((double)a)); + return (float)(scalar_log10(a)); } static float strictLOG10(float a) { - return (float)(StrictMath.log10((double)a)); + return (float)(strict_scalar_log10(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4221,11 +4420,11 @@ relativeError)); } static float EXPM1(float a) { - return (float)(Math.expm1((double)a)); + return (float)(scalar_expm1(a)); } static float strictEXPM1(float a) { - return (float)(StrictMath.expm1((double)a)); + return (float)(strict_scalar_expm1(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4244,11 +4443,11 @@ relativeError)); } static float COS(float a) { - return (float)(Math.cos((double)a)); + return (float)(scalar_cos(a)); } static float strictCOS(float a) { - return (float)(StrictMath.cos((double)a)); + return (float)(strict_scalar_cos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4267,11 +4466,11 @@ relativeError)); } static float TAN(float a) { - return (float)(Math.tan((double)a)); + return (float)(scalar_tan(a)); } static float strictTAN(float a) { - return (float)(StrictMath.tan((double)a)); + return (float)(strict_scalar_tan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4290,11 +4489,11 @@ relativeError)); } static float SINH(float a) { - return (float)(Math.sinh((double)a)); + return (float)(scalar_sinh(a)); } static float strictSINH(float a) { - return (float)(StrictMath.sinh((double)a)); + return (float)(strict_scalar_sinh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4313,11 +4512,11 @@ relativeError)); } static float COSH(float a) { - return (float)(Math.cosh((double)a)); + return (float)(scalar_cosh(a)); } static float strictCOSH(float a) { - return (float)(StrictMath.cosh((double)a)); + return (float)(strict_scalar_cosh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4336,11 +4535,11 @@ relativeError)); } static float TANH(float a) { - return (float)(Math.tanh((double)a)); + return (float)(scalar_tanh(a)); } static float strictTANH(float a) { - return (float)(StrictMath.tanh((double)a)); + return (float)(strict_scalar_tanh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4359,11 +4558,11 @@ relativeError)); } static float ASIN(float a) { - return (float)(Math.asin((double)a)); + return (float)(scalar_asin(a)); } static float strictASIN(float a) { - return (float)(StrictMath.asin((double)a)); + return (float)(strict_scalar_asin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4382,11 +4581,11 @@ relativeError)); } static float ACOS(float a) { - return (float)(Math.acos((double)a)); + return (float)(scalar_acos(a)); } static float strictACOS(float a) { - return (float)(StrictMath.acos((double)a)); + return (float)(strict_scalar_acos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4405,11 +4604,11 @@ relativeError)); } static float ATAN(float a) { - return (float)(Math.atan((double)a)); + return (float)(scalar_atan(a)); } static float strictATAN(float a) { - return (float)(StrictMath.atan((double)a)); + return (float)(strict_scalar_atan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4428,11 +4627,11 @@ relativeError)); } static float CBRT(float a) { - return (float)(Math.cbrt((double)a)); + return (float)(scalar_cbrt(a)); } static float strictCBRT(float a) { - return (float)(StrictMath.cbrt((double)a)); + return (float)(strict_scalar_cbrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4451,11 +4650,11 @@ relativeError)); } static float HYPOT(float a, float b) { - return (float)(Math.hypot((double)a, (double)b)); + return (float)(scalar_hypot(a, b)); } static float strictHYPOT(float a, float b) { - return (float)(StrictMath.hypot((double)a, (double)b)); + return (float)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4477,11 +4676,11 @@ relativeError)); static float POW(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictPOW(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4503,11 +4702,11 @@ relativeError)); static float pow(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictpow(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4529,11 +4728,11 @@ relativeError)); static float ATAN2(float a, float b) { - return (float)(Math.atan2((double)a, (double)b)); + return (float)(scalar_atan2(a, b)); } static float strictATAN2(float a, float b) { - return (float)(StrictMath.atan2((double)a, (double)b)); + return (float)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4585,11 +4784,11 @@ relativeError)); static float FMA(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } static float fma(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } @Test(dataProvider = "floatTernaryOpProvider") @@ -4767,11 +4966,11 @@ relativeError)); } static float NEG(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } static float neg(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4823,11 +5022,11 @@ relativeError)); } static float ABS(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } static float abs(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4879,11 +5078,11 @@ relativeError)); } static float SQRT(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } static float sqrt(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -5096,7 +5295,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5112,7 +5311,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5181,7 +5380,7 @@ relativeError)); static long ADDReduceLong(float[] a, int idx) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5190,7 +5389,7 @@ relativeError)); static long ADDReduceAllLong(float[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((float)res, (float)ADDReduceLong(a, i)); } return res; @@ -5208,8 +5407,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5219,8 +5418,9 @@ relativeError)); static long ADDReduceLongMasked(float[] a, int idx, boolean[] mask) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5229,7 +5429,7 @@ relativeError)); static long ADDReduceAllLongMasked(float[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((float)res, (float)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5249,8 +5449,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/FloatVector512Tests.java b/test/jdk/jdk/incubator/vector/FloatVector512Tests.java index 17493778826..6a958511439 100644 --- a/test/jdk/jdk/incubator/vector/FloatVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/FloatVector512Tests.java @@ -1601,6 +1601,205 @@ relativeError)); return Float.compare(a, (float) 0) != 0 ? a : b; } + + static float scalar_add(float a, float b) { + return (float)(a + b); + } + + static float scalar_sub(float a, float b) { + return (float)(a - b); + } + + static float scalar_mul(float a, float b) { + return (float)(a * b); + } + + static float scalar_min(float a, float b) { + return (float)(Math.min(a, b)); + } + + static float scalar_max(float a, float b) { + return (float)(Math.max(a, b)); + } + + static float scalar_div(float a, float b) { + return (float)(a / b); + } + + static float scalar_fma(float a, float b, float c) { + return (float)(Math.fma(a, b, c)); + } + + static float scalar_abs(float a) { + return (float)(Math.abs(a)); + } + + static float scalar_neg(float a) { + return ((float)-a); + } + + static float scalar_sin(float a) { + return (float)Math.sin((double)a); + } + + static float scalar_exp(float a) { + return (float)Math.exp((double)a); + } + + static float scalar_log1p(float a) { + return (float)Math.log1p((double)a); + } + + static float scalar_log(float a) { + return (float)Math.log((double)a); + } + + static float scalar_log10(float a) { + return (float)Math.log10((double)a); + } + + static float scalar_expm1(float a) { + return (float)Math.expm1((double)a); + } + + static float scalar_cos(float a) { + return (float)Math.cos((double)a); + } + + static float scalar_tan(float a) { + return (float)Math.tan((double)a); + } + + static float scalar_sinh(float a) { + return (float)Math.sinh((double)a); + } + + static float scalar_cosh(float a) { + return (float)Math.cosh((double)a); + } + + static float scalar_tanh(float a) { + return (float)Math.tanh((double)a); + } + + static float scalar_asin(float a) { + return (float)Math.asin((double)a); + } + + static float scalar_acos(float a) { + return (float)Math.acos((double)a); + } + + static float scalar_atan(float a) { + return (float)Math.atan((double)a); + } + + static float scalar_cbrt(float a) { + return (float)Math.cbrt((double)a); + } + + static float scalar_sqrt(float a) { + return (float)Math.sqrt((double)a); + } + + static float scalar_hypot(float a, float b) { + return (float)Math.hypot((double)a, (double)b); + } + + static float scalar_pow(float a, float b) { + return (float)Math.pow((double)a, (double)b); + } + + static float scalar_atan2(float a, float b) { + return (float)Math.atan2((double)a, (double)b); + } + + static float strict_scalar_sin(float a) { + return (float)StrictMath.sin((double)a); + } + + static float strict_scalar_exp(float a) { + return (float)StrictMath.exp((double)a); + } + + static float strict_scalar_log1p(float a) { + return (float)StrictMath.log1p((double)a); + } + + static float strict_scalar_log(float a) { + return (float)StrictMath.log((double)a); + } + + static float strict_scalar_log10(float a) { + return (float)StrictMath.log10((double)a); + } + + static float strict_scalar_expm1(float a) { + return (float)StrictMath.expm1((double)a); + } + + static float strict_scalar_cos(float a) { + return (float)StrictMath.cos((double)a); + } + + static float strict_scalar_tan(float a) { + return (float)StrictMath.tan((double)a); + } + + static float strict_scalar_sinh(float a) { + return (float)StrictMath.sinh((double)a); + } + + static float strict_scalar_cosh(float a) { + return (float)StrictMath.cosh((double)a); + } + + static float strict_scalar_tanh(float a) { + return (float)StrictMath.tanh((double)a); + } + + static float strict_scalar_asin(float a) { + return (float)StrictMath.asin((double)a); + } + + static float strict_scalar_acos(float a) { + return (float)StrictMath.acos((double)a); + } + + static float strict_scalar_atan(float a) { + return (float)StrictMath.atan((double)a); + } + + static float strict_scalar_cbrt(float a) { + return (float)StrictMath.cbrt((double)a); + } + + static float strict_scalar_sqrt(float a) { + return (float)StrictMath.sqrt((double)a); + } + + static float strict_scalar_hypot(float a, float b) { + return (float)StrictMath.hypot((double)a, (double)b); + } + + static float strict_scalar_pow(float a, float b) { + return (float)StrictMath.pow((double)a, (double)b); + } + + static float strict_scalar_atan2(float a, float b) { + return (float)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(float a) { + return Float.isNaN(a); + } + static boolean isFinite(float a) { + return Float.isFinite(a); + } + static boolean isInfinite(float a) { + return Float.isInfinite(a); + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -1694,7 +1893,7 @@ relativeError)); } static float ADD(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1715,7 +1914,7 @@ relativeError)); } static float add(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1772,7 +1971,7 @@ relativeError)); } static float SUB(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1793,7 +1992,7 @@ relativeError)); } static float sub(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1850,7 +2049,7 @@ relativeError)); } static float MUL(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1871,7 +2070,7 @@ relativeError)); } static float mul(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1928,7 +2127,7 @@ relativeError)); } static float DIV(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1949,7 +2148,7 @@ relativeError)); } static float div(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2006,7 +2205,7 @@ relativeError)); } static float FIRST_NONZERO(float a, float b) { - return (float)(Double.doubleToLongBits(a)!=0?a:b); + return (float)(firstNonZero(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2308,7 +2507,7 @@ relativeError)); } static float MIN(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2329,7 +2528,7 @@ relativeError)); } static float min(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2348,7 +2547,7 @@ relativeError)); } static float MAX(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2369,7 +2568,7 @@ relativeError)); } static float max(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2446,7 +2645,7 @@ relativeError)); static float ADDReduce(float[] a, int idx) { float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2455,7 +2654,7 @@ relativeError)); static float ADDReduceAll(float[] a) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2473,7 +2672,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2486,20 +2685,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = ADD_IDENTITY; - assertEquals((float) (id + id), id, + assertEquals((float) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id + x), x); - assertEquals((float) (x + id), x); + assertEquals((float) (scalar_add(id, x)), x); + assertEquals((float) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id + x), x, + assertEquals((float) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x + id), x, + assertEquals((float) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2508,7 +2707,7 @@ relativeError)); float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2517,7 +2716,7 @@ relativeError)); static float ADDReduceAllMasked(float[] a, boolean[] mask) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2537,7 +2736,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2548,7 +2747,7 @@ relativeError)); static float MULReduce(float[] a, int idx) { float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2557,7 +2756,7 @@ relativeError)); static float MULReduceAll(float[] a) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2575,7 +2774,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2588,20 +2787,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MUL_IDENTITY; - assertEquals((float) (id * id), id, + assertEquals((float) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id * x), x); - assertEquals((float) (x * id), x); + assertEquals((float) (scalar_mul(id, x)), x); + assertEquals((float) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id * x), x, + assertEquals((float) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x * id), x, + assertEquals((float) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2610,7 +2809,7 @@ relativeError)); float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2619,7 +2818,7 @@ relativeError)); static float MULReduceAllMasked(float[] a, boolean[] mask) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2639,7 +2838,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2650,7 +2849,7 @@ relativeError)); static float MINReduce(float[] a, int idx) { float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2659,7 +2858,7 @@ relativeError)); static float MINReduceAll(float[] a) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2677,7 +2876,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2690,20 +2889,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MIN_IDENTITY; - assertEquals((float) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.min(id, x), x); - assertEquals((float) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2712,7 +2911,7 @@ relativeError)); float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2721,7 +2920,7 @@ relativeError)); static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2741,7 +2940,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2752,7 +2951,7 @@ relativeError)); static float MAXReduce(float[] a, int idx) { float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2761,7 +2960,7 @@ relativeError)); static float MAXReduceAll(float[] a) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2779,7 +2978,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2792,20 +2991,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MAX_IDENTITY; - assertEquals((float) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.max(id, x), x); - assertEquals((float) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2814,7 +3013,7 @@ relativeError)); float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2823,7 +3022,7 @@ relativeError)); static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2843,7 +3042,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3055,7 +3254,7 @@ relativeError)); } static boolean testIS_FINITE(float a) { - return Float.isFinite(a); + return isFinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3096,7 +3295,7 @@ relativeError)); } static boolean testIS_NAN(float a) { - return Float.isNaN(a); + return isNaN(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3137,7 +3336,7 @@ relativeError)); } static boolean testIS_INFINITE(float a) { - return Float.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3478,7 +3677,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3498,7 +3697,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3514,7 +3713,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (float)((long)b[i]))); } } } @@ -3534,7 +3733,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (float)((long)b[i])))); } } } @@ -3550,7 +3749,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3570,7 +3769,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3586,7 +3785,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (float)((long)b[i]))); } } } @@ -3606,7 +3805,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (float)((long)b[i])))); } } } @@ -4106,11 +4305,11 @@ relativeError)); } static float SIN(float a) { - return (float)(Math.sin((double)a)); + return (float)(scalar_sin(a)); } static float strictSIN(float a) { - return (float)(StrictMath.sin((double)a)); + return (float)(strict_scalar_sin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4129,11 +4328,11 @@ relativeError)); } static float EXP(float a) { - return (float)(Math.exp((double)a)); + return (float)(scalar_exp(a)); } static float strictEXP(float a) { - return (float)(StrictMath.exp((double)a)); + return (float)(strict_scalar_exp(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4152,11 +4351,11 @@ relativeError)); } static float LOG1P(float a) { - return (float)(Math.log1p((double)a)); + return (float)(scalar_log1p(a)); } static float strictLOG1P(float a) { - return (float)(StrictMath.log1p((double)a)); + return (float)(strict_scalar_log1p(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4175,11 +4374,11 @@ relativeError)); } static float LOG(float a) { - return (float)(Math.log((double)a)); + return (float)(scalar_log(a)); } static float strictLOG(float a) { - return (float)(StrictMath.log((double)a)); + return (float)(strict_scalar_log(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4198,11 +4397,11 @@ relativeError)); } static float LOG10(float a) { - return (float)(Math.log10((double)a)); + return (float)(scalar_log10(a)); } static float strictLOG10(float a) { - return (float)(StrictMath.log10((double)a)); + return (float)(strict_scalar_log10(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4221,11 +4420,11 @@ relativeError)); } static float EXPM1(float a) { - return (float)(Math.expm1((double)a)); + return (float)(scalar_expm1(a)); } static float strictEXPM1(float a) { - return (float)(StrictMath.expm1((double)a)); + return (float)(strict_scalar_expm1(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4244,11 +4443,11 @@ relativeError)); } static float COS(float a) { - return (float)(Math.cos((double)a)); + return (float)(scalar_cos(a)); } static float strictCOS(float a) { - return (float)(StrictMath.cos((double)a)); + return (float)(strict_scalar_cos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4267,11 +4466,11 @@ relativeError)); } static float TAN(float a) { - return (float)(Math.tan((double)a)); + return (float)(scalar_tan(a)); } static float strictTAN(float a) { - return (float)(StrictMath.tan((double)a)); + return (float)(strict_scalar_tan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4290,11 +4489,11 @@ relativeError)); } static float SINH(float a) { - return (float)(Math.sinh((double)a)); + return (float)(scalar_sinh(a)); } static float strictSINH(float a) { - return (float)(StrictMath.sinh((double)a)); + return (float)(strict_scalar_sinh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4313,11 +4512,11 @@ relativeError)); } static float COSH(float a) { - return (float)(Math.cosh((double)a)); + return (float)(scalar_cosh(a)); } static float strictCOSH(float a) { - return (float)(StrictMath.cosh((double)a)); + return (float)(strict_scalar_cosh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4336,11 +4535,11 @@ relativeError)); } static float TANH(float a) { - return (float)(Math.tanh((double)a)); + return (float)(scalar_tanh(a)); } static float strictTANH(float a) { - return (float)(StrictMath.tanh((double)a)); + return (float)(strict_scalar_tanh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4359,11 +4558,11 @@ relativeError)); } static float ASIN(float a) { - return (float)(Math.asin((double)a)); + return (float)(scalar_asin(a)); } static float strictASIN(float a) { - return (float)(StrictMath.asin((double)a)); + return (float)(strict_scalar_asin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4382,11 +4581,11 @@ relativeError)); } static float ACOS(float a) { - return (float)(Math.acos((double)a)); + return (float)(scalar_acos(a)); } static float strictACOS(float a) { - return (float)(StrictMath.acos((double)a)); + return (float)(strict_scalar_acos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4405,11 +4604,11 @@ relativeError)); } static float ATAN(float a) { - return (float)(Math.atan((double)a)); + return (float)(scalar_atan(a)); } static float strictATAN(float a) { - return (float)(StrictMath.atan((double)a)); + return (float)(strict_scalar_atan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4428,11 +4627,11 @@ relativeError)); } static float CBRT(float a) { - return (float)(Math.cbrt((double)a)); + return (float)(scalar_cbrt(a)); } static float strictCBRT(float a) { - return (float)(StrictMath.cbrt((double)a)); + return (float)(strict_scalar_cbrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4451,11 +4650,11 @@ relativeError)); } static float HYPOT(float a, float b) { - return (float)(Math.hypot((double)a, (double)b)); + return (float)(scalar_hypot(a, b)); } static float strictHYPOT(float a, float b) { - return (float)(StrictMath.hypot((double)a, (double)b)); + return (float)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4477,11 +4676,11 @@ relativeError)); static float POW(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictPOW(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4503,11 +4702,11 @@ relativeError)); static float pow(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictpow(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4529,11 +4728,11 @@ relativeError)); static float ATAN2(float a, float b) { - return (float)(Math.atan2((double)a, (double)b)); + return (float)(scalar_atan2(a, b)); } static float strictATAN2(float a, float b) { - return (float)(StrictMath.atan2((double)a, (double)b)); + return (float)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4585,11 +4784,11 @@ relativeError)); static float FMA(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } static float fma(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } @Test(dataProvider = "floatTernaryOpProvider") @@ -4767,11 +4966,11 @@ relativeError)); } static float NEG(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } static float neg(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4823,11 +5022,11 @@ relativeError)); } static float ABS(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } static float abs(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4879,11 +5078,11 @@ relativeError)); } static float SQRT(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } static float sqrt(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -5096,7 +5295,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5112,7 +5311,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5181,7 +5380,7 @@ relativeError)); static long ADDReduceLong(float[] a, int idx) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5190,7 +5389,7 @@ relativeError)); static long ADDReduceAllLong(float[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((float)res, (float)ADDReduceLong(a, i)); } return res; @@ -5208,8 +5407,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5219,8 +5418,9 @@ relativeError)); static long ADDReduceLongMasked(float[] a, int idx, boolean[] mask) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5229,7 +5429,7 @@ relativeError)); static long ADDReduceAllLongMasked(float[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((float)res, (float)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5249,8 +5449,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/FloatVector64Tests.java b/test/jdk/jdk/incubator/vector/FloatVector64Tests.java index 663a56dfe26..b06dff18194 100644 --- a/test/jdk/jdk/incubator/vector/FloatVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/FloatVector64Tests.java @@ -1601,6 +1601,205 @@ relativeError)); return Float.compare(a, (float) 0) != 0 ? a : b; } + + static float scalar_add(float a, float b) { + return (float)(a + b); + } + + static float scalar_sub(float a, float b) { + return (float)(a - b); + } + + static float scalar_mul(float a, float b) { + return (float)(a * b); + } + + static float scalar_min(float a, float b) { + return (float)(Math.min(a, b)); + } + + static float scalar_max(float a, float b) { + return (float)(Math.max(a, b)); + } + + static float scalar_div(float a, float b) { + return (float)(a / b); + } + + static float scalar_fma(float a, float b, float c) { + return (float)(Math.fma(a, b, c)); + } + + static float scalar_abs(float a) { + return (float)(Math.abs(a)); + } + + static float scalar_neg(float a) { + return ((float)-a); + } + + static float scalar_sin(float a) { + return (float)Math.sin((double)a); + } + + static float scalar_exp(float a) { + return (float)Math.exp((double)a); + } + + static float scalar_log1p(float a) { + return (float)Math.log1p((double)a); + } + + static float scalar_log(float a) { + return (float)Math.log((double)a); + } + + static float scalar_log10(float a) { + return (float)Math.log10((double)a); + } + + static float scalar_expm1(float a) { + return (float)Math.expm1((double)a); + } + + static float scalar_cos(float a) { + return (float)Math.cos((double)a); + } + + static float scalar_tan(float a) { + return (float)Math.tan((double)a); + } + + static float scalar_sinh(float a) { + return (float)Math.sinh((double)a); + } + + static float scalar_cosh(float a) { + return (float)Math.cosh((double)a); + } + + static float scalar_tanh(float a) { + return (float)Math.tanh((double)a); + } + + static float scalar_asin(float a) { + return (float)Math.asin((double)a); + } + + static float scalar_acos(float a) { + return (float)Math.acos((double)a); + } + + static float scalar_atan(float a) { + return (float)Math.atan((double)a); + } + + static float scalar_cbrt(float a) { + return (float)Math.cbrt((double)a); + } + + static float scalar_sqrt(float a) { + return (float)Math.sqrt((double)a); + } + + static float scalar_hypot(float a, float b) { + return (float)Math.hypot((double)a, (double)b); + } + + static float scalar_pow(float a, float b) { + return (float)Math.pow((double)a, (double)b); + } + + static float scalar_atan2(float a, float b) { + return (float)Math.atan2((double)a, (double)b); + } + + static float strict_scalar_sin(float a) { + return (float)StrictMath.sin((double)a); + } + + static float strict_scalar_exp(float a) { + return (float)StrictMath.exp((double)a); + } + + static float strict_scalar_log1p(float a) { + return (float)StrictMath.log1p((double)a); + } + + static float strict_scalar_log(float a) { + return (float)StrictMath.log((double)a); + } + + static float strict_scalar_log10(float a) { + return (float)StrictMath.log10((double)a); + } + + static float strict_scalar_expm1(float a) { + return (float)StrictMath.expm1((double)a); + } + + static float strict_scalar_cos(float a) { + return (float)StrictMath.cos((double)a); + } + + static float strict_scalar_tan(float a) { + return (float)StrictMath.tan((double)a); + } + + static float strict_scalar_sinh(float a) { + return (float)StrictMath.sinh((double)a); + } + + static float strict_scalar_cosh(float a) { + return (float)StrictMath.cosh((double)a); + } + + static float strict_scalar_tanh(float a) { + return (float)StrictMath.tanh((double)a); + } + + static float strict_scalar_asin(float a) { + return (float)StrictMath.asin((double)a); + } + + static float strict_scalar_acos(float a) { + return (float)StrictMath.acos((double)a); + } + + static float strict_scalar_atan(float a) { + return (float)StrictMath.atan((double)a); + } + + static float strict_scalar_cbrt(float a) { + return (float)StrictMath.cbrt((double)a); + } + + static float strict_scalar_sqrt(float a) { + return (float)StrictMath.sqrt((double)a); + } + + static float strict_scalar_hypot(float a, float b) { + return (float)StrictMath.hypot((double)a, (double)b); + } + + static float strict_scalar_pow(float a, float b) { + return (float)StrictMath.pow((double)a, (double)b); + } + + static float strict_scalar_atan2(float a, float b) { + return (float)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(float a) { + return Float.isNaN(a); + } + static boolean isFinite(float a) { + return Float.isFinite(a); + } + static boolean isInfinite(float a) { + return Float.isInfinite(a); + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -1694,7 +1893,7 @@ relativeError)); } static float ADD(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1715,7 +1914,7 @@ relativeError)); } static float add(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1772,7 +1971,7 @@ relativeError)); } static float SUB(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1793,7 +1992,7 @@ relativeError)); } static float sub(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1850,7 +2049,7 @@ relativeError)); } static float MUL(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1871,7 +2070,7 @@ relativeError)); } static float mul(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1928,7 +2127,7 @@ relativeError)); } static float DIV(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1949,7 +2148,7 @@ relativeError)); } static float div(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2006,7 +2205,7 @@ relativeError)); } static float FIRST_NONZERO(float a, float b) { - return (float)(Double.doubleToLongBits(a)!=0?a:b); + return (float)(firstNonZero(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2308,7 +2507,7 @@ relativeError)); } static float MIN(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2329,7 +2528,7 @@ relativeError)); } static float min(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2348,7 +2547,7 @@ relativeError)); } static float MAX(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2369,7 +2568,7 @@ relativeError)); } static float max(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2446,7 +2645,7 @@ relativeError)); static float ADDReduce(float[] a, int idx) { float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2455,7 +2654,7 @@ relativeError)); static float ADDReduceAll(float[] a) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2473,7 +2672,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2486,20 +2685,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = ADD_IDENTITY; - assertEquals((float) (id + id), id, + assertEquals((float) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id + x), x); - assertEquals((float) (x + id), x); + assertEquals((float) (scalar_add(id, x)), x); + assertEquals((float) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id + x), x, + assertEquals((float) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x + id), x, + assertEquals((float) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2508,7 +2707,7 @@ relativeError)); float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2517,7 +2716,7 @@ relativeError)); static float ADDReduceAllMasked(float[] a, boolean[] mask) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2537,7 +2736,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2548,7 +2747,7 @@ relativeError)); static float MULReduce(float[] a, int idx) { float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2557,7 +2756,7 @@ relativeError)); static float MULReduceAll(float[] a) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2575,7 +2774,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2588,20 +2787,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MUL_IDENTITY; - assertEquals((float) (id * id), id, + assertEquals((float) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id * x), x); - assertEquals((float) (x * id), x); + assertEquals((float) (scalar_mul(id, x)), x); + assertEquals((float) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id * x), x, + assertEquals((float) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x * id), x, + assertEquals((float) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2610,7 +2809,7 @@ relativeError)); float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2619,7 +2818,7 @@ relativeError)); static float MULReduceAllMasked(float[] a, boolean[] mask) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2639,7 +2838,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2650,7 +2849,7 @@ relativeError)); static float MINReduce(float[] a, int idx) { float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2659,7 +2858,7 @@ relativeError)); static float MINReduceAll(float[] a) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2677,7 +2876,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2690,20 +2889,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MIN_IDENTITY; - assertEquals((float) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.min(id, x), x); - assertEquals((float) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2712,7 +2911,7 @@ relativeError)); float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2721,7 +2920,7 @@ relativeError)); static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2741,7 +2940,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2752,7 +2951,7 @@ relativeError)); static float MAXReduce(float[] a, int idx) { float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2761,7 +2960,7 @@ relativeError)); static float MAXReduceAll(float[] a) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2779,7 +2978,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2792,20 +2991,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MAX_IDENTITY; - assertEquals((float) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.max(id, x), x); - assertEquals((float) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2814,7 +3013,7 @@ relativeError)); float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2823,7 +3022,7 @@ relativeError)); static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2843,7 +3042,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3055,7 +3254,7 @@ relativeError)); } static boolean testIS_FINITE(float a) { - return Float.isFinite(a); + return isFinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3096,7 +3295,7 @@ relativeError)); } static boolean testIS_NAN(float a) { - return Float.isNaN(a); + return isNaN(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3137,7 +3336,7 @@ relativeError)); } static boolean testIS_INFINITE(float a) { - return Float.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3478,7 +3677,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3498,7 +3697,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3514,7 +3713,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (float)((long)b[i]))); } } } @@ -3534,7 +3733,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (float)((long)b[i])))); } } } @@ -3550,7 +3749,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3570,7 +3769,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3586,7 +3785,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (float)((long)b[i]))); } } } @@ -3606,7 +3805,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (float)((long)b[i])))); } } } @@ -4106,11 +4305,11 @@ relativeError)); } static float SIN(float a) { - return (float)(Math.sin((double)a)); + return (float)(scalar_sin(a)); } static float strictSIN(float a) { - return (float)(StrictMath.sin((double)a)); + return (float)(strict_scalar_sin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4129,11 +4328,11 @@ relativeError)); } static float EXP(float a) { - return (float)(Math.exp((double)a)); + return (float)(scalar_exp(a)); } static float strictEXP(float a) { - return (float)(StrictMath.exp((double)a)); + return (float)(strict_scalar_exp(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4152,11 +4351,11 @@ relativeError)); } static float LOG1P(float a) { - return (float)(Math.log1p((double)a)); + return (float)(scalar_log1p(a)); } static float strictLOG1P(float a) { - return (float)(StrictMath.log1p((double)a)); + return (float)(strict_scalar_log1p(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4175,11 +4374,11 @@ relativeError)); } static float LOG(float a) { - return (float)(Math.log((double)a)); + return (float)(scalar_log(a)); } static float strictLOG(float a) { - return (float)(StrictMath.log((double)a)); + return (float)(strict_scalar_log(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4198,11 +4397,11 @@ relativeError)); } static float LOG10(float a) { - return (float)(Math.log10((double)a)); + return (float)(scalar_log10(a)); } static float strictLOG10(float a) { - return (float)(StrictMath.log10((double)a)); + return (float)(strict_scalar_log10(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4221,11 +4420,11 @@ relativeError)); } static float EXPM1(float a) { - return (float)(Math.expm1((double)a)); + return (float)(scalar_expm1(a)); } static float strictEXPM1(float a) { - return (float)(StrictMath.expm1((double)a)); + return (float)(strict_scalar_expm1(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4244,11 +4443,11 @@ relativeError)); } static float COS(float a) { - return (float)(Math.cos((double)a)); + return (float)(scalar_cos(a)); } static float strictCOS(float a) { - return (float)(StrictMath.cos((double)a)); + return (float)(strict_scalar_cos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4267,11 +4466,11 @@ relativeError)); } static float TAN(float a) { - return (float)(Math.tan((double)a)); + return (float)(scalar_tan(a)); } static float strictTAN(float a) { - return (float)(StrictMath.tan((double)a)); + return (float)(strict_scalar_tan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4290,11 +4489,11 @@ relativeError)); } static float SINH(float a) { - return (float)(Math.sinh((double)a)); + return (float)(scalar_sinh(a)); } static float strictSINH(float a) { - return (float)(StrictMath.sinh((double)a)); + return (float)(strict_scalar_sinh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4313,11 +4512,11 @@ relativeError)); } static float COSH(float a) { - return (float)(Math.cosh((double)a)); + return (float)(scalar_cosh(a)); } static float strictCOSH(float a) { - return (float)(StrictMath.cosh((double)a)); + return (float)(strict_scalar_cosh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4336,11 +4535,11 @@ relativeError)); } static float TANH(float a) { - return (float)(Math.tanh((double)a)); + return (float)(scalar_tanh(a)); } static float strictTANH(float a) { - return (float)(StrictMath.tanh((double)a)); + return (float)(strict_scalar_tanh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4359,11 +4558,11 @@ relativeError)); } static float ASIN(float a) { - return (float)(Math.asin((double)a)); + return (float)(scalar_asin(a)); } static float strictASIN(float a) { - return (float)(StrictMath.asin((double)a)); + return (float)(strict_scalar_asin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4382,11 +4581,11 @@ relativeError)); } static float ACOS(float a) { - return (float)(Math.acos((double)a)); + return (float)(scalar_acos(a)); } static float strictACOS(float a) { - return (float)(StrictMath.acos((double)a)); + return (float)(strict_scalar_acos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4405,11 +4604,11 @@ relativeError)); } static float ATAN(float a) { - return (float)(Math.atan((double)a)); + return (float)(scalar_atan(a)); } static float strictATAN(float a) { - return (float)(StrictMath.atan((double)a)); + return (float)(strict_scalar_atan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4428,11 +4627,11 @@ relativeError)); } static float CBRT(float a) { - return (float)(Math.cbrt((double)a)); + return (float)(scalar_cbrt(a)); } static float strictCBRT(float a) { - return (float)(StrictMath.cbrt((double)a)); + return (float)(strict_scalar_cbrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4451,11 +4650,11 @@ relativeError)); } static float HYPOT(float a, float b) { - return (float)(Math.hypot((double)a, (double)b)); + return (float)(scalar_hypot(a, b)); } static float strictHYPOT(float a, float b) { - return (float)(StrictMath.hypot((double)a, (double)b)); + return (float)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4477,11 +4676,11 @@ relativeError)); static float POW(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictPOW(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4503,11 +4702,11 @@ relativeError)); static float pow(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictpow(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4529,11 +4728,11 @@ relativeError)); static float ATAN2(float a, float b) { - return (float)(Math.atan2((double)a, (double)b)); + return (float)(scalar_atan2(a, b)); } static float strictATAN2(float a, float b) { - return (float)(StrictMath.atan2((double)a, (double)b)); + return (float)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4585,11 +4784,11 @@ relativeError)); static float FMA(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } static float fma(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } @Test(dataProvider = "floatTernaryOpProvider") @@ -4767,11 +4966,11 @@ relativeError)); } static float NEG(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } static float neg(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4823,11 +5022,11 @@ relativeError)); } static float ABS(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } static float abs(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4879,11 +5078,11 @@ relativeError)); } static float SQRT(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } static float sqrt(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -5096,7 +5295,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5112,7 +5311,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5181,7 +5380,7 @@ relativeError)); static long ADDReduceLong(float[] a, int idx) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5190,7 +5389,7 @@ relativeError)); static long ADDReduceAllLong(float[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((float)res, (float)ADDReduceLong(a, i)); } return res; @@ -5208,8 +5407,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5219,8 +5418,9 @@ relativeError)); static long ADDReduceLongMasked(float[] a, int idx, boolean[] mask) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5229,7 +5429,7 @@ relativeError)); static long ADDReduceAllLongMasked(float[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((float)res, (float)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5249,8 +5449,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java b/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java index 9d272f43863..9b84e852c1c 100644 --- a/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/FloatVectorMaxTests.java @@ -1607,6 +1607,205 @@ relativeError)); return Float.compare(a, (float) 0) != 0 ? a : b; } + + static float scalar_add(float a, float b) { + return (float)(a + b); + } + + static float scalar_sub(float a, float b) { + return (float)(a - b); + } + + static float scalar_mul(float a, float b) { + return (float)(a * b); + } + + static float scalar_min(float a, float b) { + return (float)(Math.min(a, b)); + } + + static float scalar_max(float a, float b) { + return (float)(Math.max(a, b)); + } + + static float scalar_div(float a, float b) { + return (float)(a / b); + } + + static float scalar_fma(float a, float b, float c) { + return (float)(Math.fma(a, b, c)); + } + + static float scalar_abs(float a) { + return (float)(Math.abs(a)); + } + + static float scalar_neg(float a) { + return ((float)-a); + } + + static float scalar_sin(float a) { + return (float)Math.sin((double)a); + } + + static float scalar_exp(float a) { + return (float)Math.exp((double)a); + } + + static float scalar_log1p(float a) { + return (float)Math.log1p((double)a); + } + + static float scalar_log(float a) { + return (float)Math.log((double)a); + } + + static float scalar_log10(float a) { + return (float)Math.log10((double)a); + } + + static float scalar_expm1(float a) { + return (float)Math.expm1((double)a); + } + + static float scalar_cos(float a) { + return (float)Math.cos((double)a); + } + + static float scalar_tan(float a) { + return (float)Math.tan((double)a); + } + + static float scalar_sinh(float a) { + return (float)Math.sinh((double)a); + } + + static float scalar_cosh(float a) { + return (float)Math.cosh((double)a); + } + + static float scalar_tanh(float a) { + return (float)Math.tanh((double)a); + } + + static float scalar_asin(float a) { + return (float)Math.asin((double)a); + } + + static float scalar_acos(float a) { + return (float)Math.acos((double)a); + } + + static float scalar_atan(float a) { + return (float)Math.atan((double)a); + } + + static float scalar_cbrt(float a) { + return (float)Math.cbrt((double)a); + } + + static float scalar_sqrt(float a) { + return (float)Math.sqrt((double)a); + } + + static float scalar_hypot(float a, float b) { + return (float)Math.hypot((double)a, (double)b); + } + + static float scalar_pow(float a, float b) { + return (float)Math.pow((double)a, (double)b); + } + + static float scalar_atan2(float a, float b) { + return (float)Math.atan2((double)a, (double)b); + } + + static float strict_scalar_sin(float a) { + return (float)StrictMath.sin((double)a); + } + + static float strict_scalar_exp(float a) { + return (float)StrictMath.exp((double)a); + } + + static float strict_scalar_log1p(float a) { + return (float)StrictMath.log1p((double)a); + } + + static float strict_scalar_log(float a) { + return (float)StrictMath.log((double)a); + } + + static float strict_scalar_log10(float a) { + return (float)StrictMath.log10((double)a); + } + + static float strict_scalar_expm1(float a) { + return (float)StrictMath.expm1((double)a); + } + + static float strict_scalar_cos(float a) { + return (float)StrictMath.cos((double)a); + } + + static float strict_scalar_tan(float a) { + return (float)StrictMath.tan((double)a); + } + + static float strict_scalar_sinh(float a) { + return (float)StrictMath.sinh((double)a); + } + + static float strict_scalar_cosh(float a) { + return (float)StrictMath.cosh((double)a); + } + + static float strict_scalar_tanh(float a) { + return (float)StrictMath.tanh((double)a); + } + + static float strict_scalar_asin(float a) { + return (float)StrictMath.asin((double)a); + } + + static float strict_scalar_acos(float a) { + return (float)StrictMath.acos((double)a); + } + + static float strict_scalar_atan(float a) { + return (float)StrictMath.atan((double)a); + } + + static float strict_scalar_cbrt(float a) { + return (float)StrictMath.cbrt((double)a); + } + + static float strict_scalar_sqrt(float a) { + return (float)StrictMath.sqrt((double)a); + } + + static float strict_scalar_hypot(float a, float b) { + return (float)StrictMath.hypot((double)a, (double)b); + } + + static float strict_scalar_pow(float a, float b) { + return (float)StrictMath.pow((double)a, (double)b); + } + + static float strict_scalar_atan2(float a, float b) { + return (float)StrictMath.atan2((double)a, (double)b); + } + + static boolean isNaN(float a) { + return Float.isNaN(a); + } + static boolean isFinite(float a) { + return Float.isFinite(a); + } + static boolean isInfinite(float a) { + return Float.isInfinite(a); + } + @Test static void smokeTest1() { FloatVector three = FloatVector.broadcast(SPECIES, (byte)-3); @@ -1700,7 +1899,7 @@ relativeError)); } static float ADD(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1721,7 +1920,7 @@ relativeError)); } static float add(float a, float b) { - return (float)(a + b); + return (float)(scalar_add(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1778,7 +1977,7 @@ relativeError)); } static float SUB(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1799,7 +1998,7 @@ relativeError)); } static float sub(float a, float b) { - return (float)(a - b); + return (float)(scalar_sub(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1856,7 +2055,7 @@ relativeError)); } static float MUL(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1877,7 +2076,7 @@ relativeError)); } static float mul(float a, float b) { - return (float)(a * b); + return (float)(scalar_mul(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1934,7 +2133,7 @@ relativeError)); } static float DIV(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -1955,7 +2154,7 @@ relativeError)); } static float div(float a, float b) { - return (float)(a / b); + return (float)(scalar_div(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2012,7 +2211,7 @@ relativeError)); } static float FIRST_NONZERO(float a, float b) { - return (float)(Double.doubleToLongBits(a)!=0?a:b); + return (float)(firstNonZero(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2314,7 +2513,7 @@ relativeError)); } static float MIN(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2335,7 +2534,7 @@ relativeError)); } static float min(float a, float b) { - return (float)(Math.min(a, b)); + return (float)(scalar_min(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2354,7 +2553,7 @@ relativeError)); } static float MAX(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2375,7 +2574,7 @@ relativeError)); } static float max(float a, float b) { - return (float)(Math.max(a, b)); + return (float)(scalar_max(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -2452,7 +2651,7 @@ relativeError)); static float ADDReduce(float[] a, int idx) { float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2461,7 +2660,7 @@ relativeError)); static float ADDReduceAll(float[] a) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -2479,7 +2678,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2492,20 +2691,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = ADD_IDENTITY; - assertEquals((float) (id + id), id, + assertEquals((float) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id + x), x); - assertEquals((float) (x + id), x); + assertEquals((float) (scalar_add(id, x)), x); + assertEquals((float) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id + x), x, + assertEquals((float) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x + id), x, + assertEquals((float) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -2514,7 +2713,7 @@ relativeError)); float res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -2523,7 +2722,7 @@ relativeError)); static float ADDReduceAllMasked(float[] a, boolean[] mask) { float res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -2543,7 +2742,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -2554,7 +2753,7 @@ relativeError)); static float MULReduce(float[] a, int idx) { float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2563,7 +2762,7 @@ relativeError)); static float MULReduceAll(float[] a) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -2581,7 +2780,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2594,20 +2793,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MUL_IDENTITY; - assertEquals((float) (id * id), id, + assertEquals((float) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) (id * x), x); - assertEquals((float) (x * id), x); + assertEquals((float) (scalar_mul(id, x)), x); + assertEquals((float) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((float) (id * x), x, + assertEquals((float) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((float) (x * id), x, + assertEquals((float) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -2616,7 +2815,7 @@ relativeError)); float res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -2625,7 +2824,7 @@ relativeError)); static float MULReduceAllMasked(float[] a, boolean[] mask) { float res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -2645,7 +2844,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -2656,7 +2855,7 @@ relativeError)); static float MINReduce(float[] a, int idx) { float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2665,7 +2864,7 @@ relativeError)); static float MINReduceAll(float[] a) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -2683,7 +2882,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2696,20 +2895,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MIN_IDENTITY; - assertEquals((float) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.min(id, x), x); - assertEquals((float) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -2718,7 +2917,7 @@ relativeError)); float res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -2727,7 +2926,7 @@ relativeError)); static float MINReduceAllMasked(float[] a, boolean[] mask) { float res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -2747,7 +2946,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (float) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -2758,7 +2957,7 @@ relativeError)); static float MAXReduce(float[] a, int idx) { float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2767,7 +2966,7 @@ relativeError)); static float MAXReduceAll(float[] a) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -2785,7 +2984,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -2798,20 +2997,20 @@ relativeError)); float[] a = fa.apply(SPECIES.length()); float id = MAX_IDENTITY; - assertEquals((float) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); float x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((float) Math.max(id, x), x); - assertEquals((float) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((float) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((float) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -2820,7 +3019,7 @@ relativeError)); float res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (float) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -2829,7 +3028,7 @@ relativeError)); static float MAXReduceAllMasked(float[] a, boolean[] mask) { float res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (float) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -2849,7 +3048,7 @@ relativeError)); FloatVector av = FloatVector.fromArray(SPECIES, a, i); float v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (float) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -3061,7 +3260,7 @@ relativeError)); } static boolean testIS_FINITE(float a) { - return Float.isFinite(a); + return isFinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3102,7 +3301,7 @@ relativeError)); } static boolean testIS_NAN(float a) { - return Float.isNaN(a); + return isNaN(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3143,7 +3342,7 @@ relativeError)); } static boolean testIS_INFINITE(float a) { - return Float.isInfinite(a); + return isInfinite(a); } @Test(dataProvider = "floatTestOpProvider") @@ -3484,7 +3683,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -3504,7 +3703,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -3520,7 +3719,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (float)((long)b[i]))); } } } @@ -3540,7 +3739,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (float)((long)b[i])))); } } } @@ -3556,7 +3755,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -3576,7 +3775,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -3592,7 +3791,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (float)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (float)((long)b[i]))); } } } @@ -3612,7 +3811,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (float)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (float)((long)b[i])))); } } } @@ -4112,11 +4311,11 @@ relativeError)); } static float SIN(float a) { - return (float)(Math.sin((double)a)); + return (float)(scalar_sin(a)); } static float strictSIN(float a) { - return (float)(StrictMath.sin((double)a)); + return (float)(strict_scalar_sin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4135,11 +4334,11 @@ relativeError)); } static float EXP(float a) { - return (float)(Math.exp((double)a)); + return (float)(scalar_exp(a)); } static float strictEXP(float a) { - return (float)(StrictMath.exp((double)a)); + return (float)(strict_scalar_exp(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4158,11 +4357,11 @@ relativeError)); } static float LOG1P(float a) { - return (float)(Math.log1p((double)a)); + return (float)(scalar_log1p(a)); } static float strictLOG1P(float a) { - return (float)(StrictMath.log1p((double)a)); + return (float)(strict_scalar_log1p(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4181,11 +4380,11 @@ relativeError)); } static float LOG(float a) { - return (float)(Math.log((double)a)); + return (float)(scalar_log(a)); } static float strictLOG(float a) { - return (float)(StrictMath.log((double)a)); + return (float)(strict_scalar_log(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4204,11 +4403,11 @@ relativeError)); } static float LOG10(float a) { - return (float)(Math.log10((double)a)); + return (float)(scalar_log10(a)); } static float strictLOG10(float a) { - return (float)(StrictMath.log10((double)a)); + return (float)(strict_scalar_log10(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4227,11 +4426,11 @@ relativeError)); } static float EXPM1(float a) { - return (float)(Math.expm1((double)a)); + return (float)(scalar_expm1(a)); } static float strictEXPM1(float a) { - return (float)(StrictMath.expm1((double)a)); + return (float)(strict_scalar_expm1(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4250,11 +4449,11 @@ relativeError)); } static float COS(float a) { - return (float)(Math.cos((double)a)); + return (float)(scalar_cos(a)); } static float strictCOS(float a) { - return (float)(StrictMath.cos((double)a)); + return (float)(strict_scalar_cos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4273,11 +4472,11 @@ relativeError)); } static float TAN(float a) { - return (float)(Math.tan((double)a)); + return (float)(scalar_tan(a)); } static float strictTAN(float a) { - return (float)(StrictMath.tan((double)a)); + return (float)(strict_scalar_tan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4296,11 +4495,11 @@ relativeError)); } static float SINH(float a) { - return (float)(Math.sinh((double)a)); + return (float)(scalar_sinh(a)); } static float strictSINH(float a) { - return (float)(StrictMath.sinh((double)a)); + return (float)(strict_scalar_sinh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4319,11 +4518,11 @@ relativeError)); } static float COSH(float a) { - return (float)(Math.cosh((double)a)); + return (float)(scalar_cosh(a)); } static float strictCOSH(float a) { - return (float)(StrictMath.cosh((double)a)); + return (float)(strict_scalar_cosh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4342,11 +4541,11 @@ relativeError)); } static float TANH(float a) { - return (float)(Math.tanh((double)a)); + return (float)(scalar_tanh(a)); } static float strictTANH(float a) { - return (float)(StrictMath.tanh((double)a)); + return (float)(strict_scalar_tanh(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4365,11 +4564,11 @@ relativeError)); } static float ASIN(float a) { - return (float)(Math.asin((double)a)); + return (float)(scalar_asin(a)); } static float strictASIN(float a) { - return (float)(StrictMath.asin((double)a)); + return (float)(strict_scalar_asin(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4388,11 +4587,11 @@ relativeError)); } static float ACOS(float a) { - return (float)(Math.acos((double)a)); + return (float)(scalar_acos(a)); } static float strictACOS(float a) { - return (float)(StrictMath.acos((double)a)); + return (float)(strict_scalar_acos(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4411,11 +4610,11 @@ relativeError)); } static float ATAN(float a) { - return (float)(Math.atan((double)a)); + return (float)(scalar_atan(a)); } static float strictATAN(float a) { - return (float)(StrictMath.atan((double)a)); + return (float)(strict_scalar_atan(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4434,11 +4633,11 @@ relativeError)); } static float CBRT(float a) { - return (float)(Math.cbrt((double)a)); + return (float)(scalar_cbrt(a)); } static float strictCBRT(float a) { - return (float)(StrictMath.cbrt((double)a)); + return (float)(strict_scalar_cbrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4457,11 +4656,11 @@ relativeError)); } static float HYPOT(float a, float b) { - return (float)(Math.hypot((double)a, (double)b)); + return (float)(scalar_hypot(a, b)); } static float strictHYPOT(float a, float b) { - return (float)(StrictMath.hypot((double)a, (double)b)); + return (float)(strict_scalar_hypot(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4483,11 +4682,11 @@ relativeError)); static float POW(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictPOW(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4509,11 +4708,11 @@ relativeError)); static float pow(float a, float b) { - return (float)(Math.pow((double)a, (double)b)); + return (float)(scalar_pow(a, b)); } static float strictpow(float a, float b) { - return (float)(StrictMath.pow((double)a, (double)b)); + return (float)(strict_scalar_pow(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4535,11 +4734,11 @@ relativeError)); static float ATAN2(float a, float b) { - return (float)(Math.atan2((double)a, (double)b)); + return (float)(scalar_atan2(a, b)); } static float strictATAN2(float a, float b) { - return (float)(StrictMath.atan2((double)a, (double)b)); + return (float)(strict_scalar_atan2(a, b)); } @Test(dataProvider = "floatBinaryOpProvider") @@ -4591,11 +4790,11 @@ relativeError)); static float FMA(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } static float fma(float a, float b, float c) { - return (float)(Math.fma(a, b, c)); + return (float)(scalar_fma(a, b, c)); } @Test(dataProvider = "floatTernaryOpProvider") @@ -4773,11 +4972,11 @@ relativeError)); } static float NEG(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } static float neg(float a) { - return (float)(-((float)a)); + return (float)(scalar_neg((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4829,11 +5028,11 @@ relativeError)); } static float ABS(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } static float abs(float a) { - return (float)(Math.abs((float)a)); + return (float)(scalar_abs((float)a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -4885,11 +5084,11 @@ relativeError)); } static float SQRT(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } static float sqrt(float a) { - return (float)(Math.sqrt((double)a)); + return (float)(scalar_sqrt(a)); } @Test(dataProvider = "floatUnaryOpProvider") @@ -5102,7 +5301,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5118,7 +5317,7 @@ relativeError)); // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5187,7 +5386,7 @@ relativeError)); static long ADDReduceLong(float[] a, int idx) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -5196,7 +5395,7 @@ relativeError)); static long ADDReduceAllLong(float[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((float)res, (float)ADDReduceLong(a, i)); } return res; @@ -5214,8 +5413,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -5225,8 +5424,9 @@ relativeError)); static long ADDReduceLongMasked(float[] a, int idx, boolean[] mask) { float res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -5235,7 +5435,7 @@ relativeError)); static long ADDReduceAllLongMasked(float[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((float)res, (float)ADDReduceLongMasked(a, i, mask)); } return res; @@ -5255,8 +5455,8 @@ relativeError)); } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((float)ra, (float)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/IntVector128Tests.java b/test/jdk/jdk/incubator/vector/IntVector128Tests.java index ecdb23eb40d..d62f5d8df00 100644 --- a/test/jdk/jdk/incubator/vector/IntVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/IntVector128Tests.java @@ -1531,6 +1531,59 @@ public class IntVector128Tests extends AbstractVectorTest { return a >= b; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + + static int scalar_or(int a, int b) { + return (int)(a | b); + } + + static int scalar_and(int a, int b) { + return (int)(a & b); + } + + static int scalar_xor(int a, int b) { + return (int)(a ^ b); + } + + static int scalar_add(int a, int b) { + return (int)(a + b); + } + + static int scalar_sub(int a, int b) { + return (int)(a - b); + } + + static int scalar_mul(int a, int b) { + return (int)(a * b); + } + + static int scalar_min(int a, int b) { + return (int)(Math.min(a, b)); + } + + static int scalar_max(int a, int b) { + return (int)(Math.max(a, b)); + } + + static int scalar_div(int a, int b) { + return (int)(a / b); + } + + static int scalar_fma(int a, int b, int c) { + return (int)(Math.fma(a, b, c)); + } + + static int scalar_abs(int a) { + return (int)(Math.abs(a)); + } + + static int scalar_neg(int a) { + return ((int)-a); + } + + static boolean ult(int a, int b) { return Integer.compareUnsigned(a, b) < 0; } @@ -1547,9 +1600,6 @@ public class IntVector128Tests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } - static int firstNonZero(int a, int b) { - return Integer.compare(a, (int) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1663,7 +1713,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int ADD(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1684,7 +1734,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int add(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1741,7 +1791,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int SUB(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1762,7 +1812,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int sub(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1819,7 +1869,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int MUL(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1840,7 +1890,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int mul(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1987,7 +2037,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int FIRST_NONZERO(int a, int b) { - return (int)((a)!=0?a:b); + return (int)(firstNonZero(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3283,7 +3333,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int MIN(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3304,7 +3354,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int min(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3323,7 +3373,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int MAX(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3344,7 +3394,7 @@ public class IntVector128Tests extends AbstractVectorTest { } static int max(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3712,7 +3762,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ANDReduce(int[] a, int idx) { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3721,7 +3771,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ANDReduceAll(int[] a) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3739,7 +3789,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3752,20 +3802,20 @@ public class IntVector128Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = AND_IDENTITY; - assertEquals((int) (id & id), id, + assertEquals((int) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id & x), x); - assertEquals((int) (x & id), x); + assertEquals((int) (scalar_and(id, x)), x); + assertEquals((int) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id & x), x, + assertEquals((int) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x & id), x, + assertEquals((int) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3774,7 +3824,7 @@ public class IntVector128Tests extends AbstractVectorTest { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3783,7 +3833,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ANDReduceAllMasked(int[] a, boolean[] mask) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3803,7 +3853,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3814,7 +3864,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ORReduce(int[] a, int idx) { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3823,7 +3873,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ORReduceAll(int[] a) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3841,7 +3891,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3854,20 +3904,20 @@ public class IntVector128Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = OR_IDENTITY; - assertEquals((int) (id | id), id, + assertEquals((int) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id | x), x); - assertEquals((int) (x | id), x); + assertEquals((int) (scalar_or(id, x)), x); + assertEquals((int) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id | x), x, + assertEquals((int) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x | id), x, + assertEquals((int) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3876,7 +3926,7 @@ public class IntVector128Tests extends AbstractVectorTest { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3885,7 +3935,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ORReduceAllMasked(int[] a, boolean[] mask) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3905,7 +3955,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3916,7 +3966,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int XORReduce(int[] a, int idx) { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3925,7 +3975,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int XORReduceAll(int[] a) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3943,7 +3993,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3956,20 +4006,20 @@ public class IntVector128Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = XOR_IDENTITY; - assertEquals((int) (id ^ id), id, + assertEquals((int) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id ^ x), x); - assertEquals((int) (x ^ id), x); + assertEquals((int) (scalar_xor(id, x)), x); + assertEquals((int) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id ^ x), x, + assertEquals((int) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x ^ id), x, + assertEquals((int) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3978,7 +4028,7 @@ public class IntVector128Tests extends AbstractVectorTest { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3987,7 +4037,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int XORReduceAllMasked(int[] a, boolean[] mask) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4007,7 +4057,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4018,7 +4068,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ADDReduce(int[] a, int idx) { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4027,7 +4077,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ADDReduceAll(int[] a) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4045,7 +4095,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4058,20 +4108,20 @@ public class IntVector128Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = ADD_IDENTITY; - assertEquals((int) (id + id), id, + assertEquals((int) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id + x), x); - assertEquals((int) (x + id), x); + assertEquals((int) (scalar_add(id, x)), x); + assertEquals((int) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id + x), x, + assertEquals((int) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x + id), x, + assertEquals((int) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4080,7 +4130,7 @@ public class IntVector128Tests extends AbstractVectorTest { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4089,7 +4139,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int ADDReduceAllMasked(int[] a, boolean[] mask) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4109,7 +4159,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4120,7 +4170,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MULReduce(int[] a, int idx) { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4129,7 +4179,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MULReduceAll(int[] a) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4147,7 +4197,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4160,20 +4210,20 @@ public class IntVector128Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MUL_IDENTITY; - assertEquals((int) (id * id), id, + assertEquals((int) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id * x), x); - assertEquals((int) (x * id), x); + assertEquals((int) (scalar_mul(id, x)), x); + assertEquals((int) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id * x), x, + assertEquals((int) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x * id), x, + assertEquals((int) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4182,7 +4232,7 @@ public class IntVector128Tests extends AbstractVectorTest { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4191,7 +4241,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MULReduceAllMasked(int[] a, boolean[] mask) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4211,7 +4261,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4222,7 +4272,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4231,7 +4281,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4249,7 +4299,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4262,20 +4312,20 @@ public class IntVector128Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MIN_IDENTITY; - assertEquals((int) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.min(id, x), x); - assertEquals((int) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4284,7 +4334,7 @@ public class IntVector128Tests extends AbstractVectorTest { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4293,7 +4343,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4313,7 +4363,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4324,7 +4374,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4333,7 +4383,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4351,7 +4401,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4364,20 +4414,20 @@ public class IntVector128Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MAX_IDENTITY; - assertEquals((int) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.max(id, x), x); - assertEquals((int) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4386,7 +4436,7 @@ public class IntVector128Tests extends AbstractVectorTest { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4395,7 +4445,7 @@ public class IntVector128Tests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4415,7 +4465,7 @@ public class IntVector128Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5448,7 +5498,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5468,7 +5518,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5484,7 +5534,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (int)((long)b[i]))); } } } @@ -5504,7 +5554,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (int)((long)b[i])))); } } } @@ -5520,7 +5570,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5540,7 +5590,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5556,7 +5606,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (int)((long)b[i]))); } } } @@ -5576,7 +5626,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (int)((long)b[i])))); } } } @@ -6288,11 +6338,11 @@ public class IntVector128Tests extends AbstractVectorTest { } static int NEG(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } static int neg(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6344,11 +6394,11 @@ public class IntVector128Tests extends AbstractVectorTest { } static int ABS(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } static int abs(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6839,7 +6889,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6855,7 +6905,7 @@ public class IntVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6924,7 +6974,7 @@ public class IntVector128Tests extends AbstractVectorTest { static long ADDReduceLong(int[] a, int idx) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6933,7 +6983,7 @@ public class IntVector128Tests extends AbstractVectorTest { static long ADDReduceAllLong(int[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((int)res, (int)ADDReduceLong(a, i)); } return res; @@ -6951,8 +7001,8 @@ public class IntVector128Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6962,8 +7012,9 @@ public class IntVector128Tests extends AbstractVectorTest { static long ADDReduceLongMasked(int[] a, int idx, boolean[] mask) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6972,7 +7023,7 @@ public class IntVector128Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(int[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((int)res, (int)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6992,8 +7043,8 @@ public class IntVector128Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/IntVector256Tests.java b/test/jdk/jdk/incubator/vector/IntVector256Tests.java index 7100ebd1693..bb2d1d717f4 100644 --- a/test/jdk/jdk/incubator/vector/IntVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/IntVector256Tests.java @@ -1531,6 +1531,59 @@ public class IntVector256Tests extends AbstractVectorTest { return a >= b; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + + static int scalar_or(int a, int b) { + return (int)(a | b); + } + + static int scalar_and(int a, int b) { + return (int)(a & b); + } + + static int scalar_xor(int a, int b) { + return (int)(a ^ b); + } + + static int scalar_add(int a, int b) { + return (int)(a + b); + } + + static int scalar_sub(int a, int b) { + return (int)(a - b); + } + + static int scalar_mul(int a, int b) { + return (int)(a * b); + } + + static int scalar_min(int a, int b) { + return (int)(Math.min(a, b)); + } + + static int scalar_max(int a, int b) { + return (int)(Math.max(a, b)); + } + + static int scalar_div(int a, int b) { + return (int)(a / b); + } + + static int scalar_fma(int a, int b, int c) { + return (int)(Math.fma(a, b, c)); + } + + static int scalar_abs(int a) { + return (int)(Math.abs(a)); + } + + static int scalar_neg(int a) { + return ((int)-a); + } + + static boolean ult(int a, int b) { return Integer.compareUnsigned(a, b) < 0; } @@ -1547,9 +1600,6 @@ public class IntVector256Tests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } - static int firstNonZero(int a, int b) { - return Integer.compare(a, (int) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1663,7 +1713,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int ADD(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1684,7 +1734,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int add(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1741,7 +1791,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int SUB(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1762,7 +1812,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int sub(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1819,7 +1869,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int MUL(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1840,7 +1890,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int mul(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1987,7 +2037,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int FIRST_NONZERO(int a, int b) { - return (int)((a)!=0?a:b); + return (int)(firstNonZero(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3283,7 +3333,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int MIN(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3304,7 +3354,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int min(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3323,7 +3373,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int MAX(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3344,7 +3394,7 @@ public class IntVector256Tests extends AbstractVectorTest { } static int max(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3712,7 +3762,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ANDReduce(int[] a, int idx) { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3721,7 +3771,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ANDReduceAll(int[] a) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3739,7 +3789,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3752,20 +3802,20 @@ public class IntVector256Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = AND_IDENTITY; - assertEquals((int) (id & id), id, + assertEquals((int) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id & x), x); - assertEquals((int) (x & id), x); + assertEquals((int) (scalar_and(id, x)), x); + assertEquals((int) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id & x), x, + assertEquals((int) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x & id), x, + assertEquals((int) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3774,7 +3824,7 @@ public class IntVector256Tests extends AbstractVectorTest { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3783,7 +3833,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ANDReduceAllMasked(int[] a, boolean[] mask) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3803,7 +3853,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3814,7 +3864,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ORReduce(int[] a, int idx) { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3823,7 +3873,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ORReduceAll(int[] a) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3841,7 +3891,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3854,20 +3904,20 @@ public class IntVector256Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = OR_IDENTITY; - assertEquals((int) (id | id), id, + assertEquals((int) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id | x), x); - assertEquals((int) (x | id), x); + assertEquals((int) (scalar_or(id, x)), x); + assertEquals((int) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id | x), x, + assertEquals((int) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x | id), x, + assertEquals((int) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3876,7 +3926,7 @@ public class IntVector256Tests extends AbstractVectorTest { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3885,7 +3935,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ORReduceAllMasked(int[] a, boolean[] mask) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3905,7 +3955,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3916,7 +3966,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int XORReduce(int[] a, int idx) { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3925,7 +3975,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int XORReduceAll(int[] a) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3943,7 +3993,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3956,20 +4006,20 @@ public class IntVector256Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = XOR_IDENTITY; - assertEquals((int) (id ^ id), id, + assertEquals((int) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id ^ x), x); - assertEquals((int) (x ^ id), x); + assertEquals((int) (scalar_xor(id, x)), x); + assertEquals((int) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id ^ x), x, + assertEquals((int) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x ^ id), x, + assertEquals((int) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3978,7 +4028,7 @@ public class IntVector256Tests extends AbstractVectorTest { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3987,7 +4037,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int XORReduceAllMasked(int[] a, boolean[] mask) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4007,7 +4057,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4018,7 +4068,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ADDReduce(int[] a, int idx) { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4027,7 +4077,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ADDReduceAll(int[] a) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4045,7 +4095,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4058,20 +4108,20 @@ public class IntVector256Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = ADD_IDENTITY; - assertEquals((int) (id + id), id, + assertEquals((int) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id + x), x); - assertEquals((int) (x + id), x); + assertEquals((int) (scalar_add(id, x)), x); + assertEquals((int) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id + x), x, + assertEquals((int) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x + id), x, + assertEquals((int) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4080,7 +4130,7 @@ public class IntVector256Tests extends AbstractVectorTest { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4089,7 +4139,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int ADDReduceAllMasked(int[] a, boolean[] mask) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4109,7 +4159,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4120,7 +4170,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MULReduce(int[] a, int idx) { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4129,7 +4179,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MULReduceAll(int[] a) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4147,7 +4197,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4160,20 +4210,20 @@ public class IntVector256Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MUL_IDENTITY; - assertEquals((int) (id * id), id, + assertEquals((int) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id * x), x); - assertEquals((int) (x * id), x); + assertEquals((int) (scalar_mul(id, x)), x); + assertEquals((int) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id * x), x, + assertEquals((int) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x * id), x, + assertEquals((int) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4182,7 +4232,7 @@ public class IntVector256Tests extends AbstractVectorTest { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4191,7 +4241,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MULReduceAllMasked(int[] a, boolean[] mask) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4211,7 +4261,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4222,7 +4272,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4231,7 +4281,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4249,7 +4299,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4262,20 +4312,20 @@ public class IntVector256Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MIN_IDENTITY; - assertEquals((int) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.min(id, x), x); - assertEquals((int) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4284,7 +4334,7 @@ public class IntVector256Tests extends AbstractVectorTest { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4293,7 +4343,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4313,7 +4363,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4324,7 +4374,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4333,7 +4383,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4351,7 +4401,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4364,20 +4414,20 @@ public class IntVector256Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MAX_IDENTITY; - assertEquals((int) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.max(id, x), x); - assertEquals((int) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4386,7 +4436,7 @@ public class IntVector256Tests extends AbstractVectorTest { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4395,7 +4445,7 @@ public class IntVector256Tests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4415,7 +4465,7 @@ public class IntVector256Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5448,7 +5498,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5468,7 +5518,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5484,7 +5534,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (int)((long)b[i]))); } } } @@ -5504,7 +5554,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (int)((long)b[i])))); } } } @@ -5520,7 +5570,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5540,7 +5590,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5556,7 +5606,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (int)((long)b[i]))); } } } @@ -5576,7 +5626,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (int)((long)b[i])))); } } } @@ -6288,11 +6338,11 @@ public class IntVector256Tests extends AbstractVectorTest { } static int NEG(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } static int neg(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6344,11 +6394,11 @@ public class IntVector256Tests extends AbstractVectorTest { } static int ABS(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } static int abs(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6839,7 +6889,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6855,7 +6905,7 @@ public class IntVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6924,7 +6974,7 @@ public class IntVector256Tests extends AbstractVectorTest { static long ADDReduceLong(int[] a, int idx) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6933,7 +6983,7 @@ public class IntVector256Tests extends AbstractVectorTest { static long ADDReduceAllLong(int[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((int)res, (int)ADDReduceLong(a, i)); } return res; @@ -6951,8 +7001,8 @@ public class IntVector256Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6962,8 +7012,9 @@ public class IntVector256Tests extends AbstractVectorTest { static long ADDReduceLongMasked(int[] a, int idx, boolean[] mask) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6972,7 +7023,7 @@ public class IntVector256Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(int[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((int)res, (int)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6992,8 +7043,8 @@ public class IntVector256Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/IntVector512Tests.java b/test/jdk/jdk/incubator/vector/IntVector512Tests.java index 468d3b15efe..5ceba4e88ec 100644 --- a/test/jdk/jdk/incubator/vector/IntVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/IntVector512Tests.java @@ -1531,6 +1531,59 @@ public class IntVector512Tests extends AbstractVectorTest { return a >= b; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + + static int scalar_or(int a, int b) { + return (int)(a | b); + } + + static int scalar_and(int a, int b) { + return (int)(a & b); + } + + static int scalar_xor(int a, int b) { + return (int)(a ^ b); + } + + static int scalar_add(int a, int b) { + return (int)(a + b); + } + + static int scalar_sub(int a, int b) { + return (int)(a - b); + } + + static int scalar_mul(int a, int b) { + return (int)(a * b); + } + + static int scalar_min(int a, int b) { + return (int)(Math.min(a, b)); + } + + static int scalar_max(int a, int b) { + return (int)(Math.max(a, b)); + } + + static int scalar_div(int a, int b) { + return (int)(a / b); + } + + static int scalar_fma(int a, int b, int c) { + return (int)(Math.fma(a, b, c)); + } + + static int scalar_abs(int a) { + return (int)(Math.abs(a)); + } + + static int scalar_neg(int a) { + return ((int)-a); + } + + static boolean ult(int a, int b) { return Integer.compareUnsigned(a, b) < 0; } @@ -1547,9 +1600,6 @@ public class IntVector512Tests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } - static int firstNonZero(int a, int b) { - return Integer.compare(a, (int) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1663,7 +1713,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int ADD(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1684,7 +1734,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int add(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1741,7 +1791,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int SUB(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1762,7 +1812,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int sub(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1819,7 +1869,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int MUL(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1840,7 +1890,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int mul(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1987,7 +2037,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int FIRST_NONZERO(int a, int b) { - return (int)((a)!=0?a:b); + return (int)(firstNonZero(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3283,7 +3333,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int MIN(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3304,7 +3354,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int min(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3323,7 +3373,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int MAX(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3344,7 +3394,7 @@ public class IntVector512Tests extends AbstractVectorTest { } static int max(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3712,7 +3762,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ANDReduce(int[] a, int idx) { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3721,7 +3771,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ANDReduceAll(int[] a) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3739,7 +3789,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3752,20 +3802,20 @@ public class IntVector512Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = AND_IDENTITY; - assertEquals((int) (id & id), id, + assertEquals((int) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id & x), x); - assertEquals((int) (x & id), x); + assertEquals((int) (scalar_and(id, x)), x); + assertEquals((int) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id & x), x, + assertEquals((int) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x & id), x, + assertEquals((int) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3774,7 +3824,7 @@ public class IntVector512Tests extends AbstractVectorTest { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3783,7 +3833,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ANDReduceAllMasked(int[] a, boolean[] mask) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3803,7 +3853,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3814,7 +3864,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ORReduce(int[] a, int idx) { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3823,7 +3873,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ORReduceAll(int[] a) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3841,7 +3891,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3854,20 +3904,20 @@ public class IntVector512Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = OR_IDENTITY; - assertEquals((int) (id | id), id, + assertEquals((int) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id | x), x); - assertEquals((int) (x | id), x); + assertEquals((int) (scalar_or(id, x)), x); + assertEquals((int) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id | x), x, + assertEquals((int) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x | id), x, + assertEquals((int) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3876,7 +3926,7 @@ public class IntVector512Tests extends AbstractVectorTest { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3885,7 +3935,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ORReduceAllMasked(int[] a, boolean[] mask) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3905,7 +3955,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3916,7 +3966,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int XORReduce(int[] a, int idx) { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3925,7 +3975,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int XORReduceAll(int[] a) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3943,7 +3993,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3956,20 +4006,20 @@ public class IntVector512Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = XOR_IDENTITY; - assertEquals((int) (id ^ id), id, + assertEquals((int) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id ^ x), x); - assertEquals((int) (x ^ id), x); + assertEquals((int) (scalar_xor(id, x)), x); + assertEquals((int) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id ^ x), x, + assertEquals((int) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x ^ id), x, + assertEquals((int) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3978,7 +4028,7 @@ public class IntVector512Tests extends AbstractVectorTest { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3987,7 +4037,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int XORReduceAllMasked(int[] a, boolean[] mask) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4007,7 +4057,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4018,7 +4068,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ADDReduce(int[] a, int idx) { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4027,7 +4077,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ADDReduceAll(int[] a) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4045,7 +4095,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4058,20 +4108,20 @@ public class IntVector512Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = ADD_IDENTITY; - assertEquals((int) (id + id), id, + assertEquals((int) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id + x), x); - assertEquals((int) (x + id), x); + assertEquals((int) (scalar_add(id, x)), x); + assertEquals((int) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id + x), x, + assertEquals((int) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x + id), x, + assertEquals((int) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4080,7 +4130,7 @@ public class IntVector512Tests extends AbstractVectorTest { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4089,7 +4139,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int ADDReduceAllMasked(int[] a, boolean[] mask) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4109,7 +4159,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4120,7 +4170,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MULReduce(int[] a, int idx) { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4129,7 +4179,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MULReduceAll(int[] a) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4147,7 +4197,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4160,20 +4210,20 @@ public class IntVector512Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MUL_IDENTITY; - assertEquals((int) (id * id), id, + assertEquals((int) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id * x), x); - assertEquals((int) (x * id), x); + assertEquals((int) (scalar_mul(id, x)), x); + assertEquals((int) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id * x), x, + assertEquals((int) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x * id), x, + assertEquals((int) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4182,7 +4232,7 @@ public class IntVector512Tests extends AbstractVectorTest { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4191,7 +4241,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MULReduceAllMasked(int[] a, boolean[] mask) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4211,7 +4261,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4222,7 +4272,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4231,7 +4281,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4249,7 +4299,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4262,20 +4312,20 @@ public class IntVector512Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MIN_IDENTITY; - assertEquals((int) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.min(id, x), x); - assertEquals((int) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4284,7 +4334,7 @@ public class IntVector512Tests extends AbstractVectorTest { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4293,7 +4343,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4313,7 +4363,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4324,7 +4374,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4333,7 +4383,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4351,7 +4401,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4364,20 +4414,20 @@ public class IntVector512Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MAX_IDENTITY; - assertEquals((int) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.max(id, x), x); - assertEquals((int) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4386,7 +4436,7 @@ public class IntVector512Tests extends AbstractVectorTest { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4395,7 +4445,7 @@ public class IntVector512Tests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4415,7 +4465,7 @@ public class IntVector512Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5448,7 +5498,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5468,7 +5518,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5484,7 +5534,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (int)((long)b[i]))); } } } @@ -5504,7 +5554,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (int)((long)b[i])))); } } } @@ -5520,7 +5570,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5540,7 +5590,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5556,7 +5606,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (int)((long)b[i]))); } } } @@ -5576,7 +5626,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (int)((long)b[i])))); } } } @@ -6288,11 +6338,11 @@ public class IntVector512Tests extends AbstractVectorTest { } static int NEG(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } static int neg(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6344,11 +6394,11 @@ public class IntVector512Tests extends AbstractVectorTest { } static int ABS(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } static int abs(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6839,7 +6889,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6855,7 +6905,7 @@ public class IntVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6924,7 +6974,7 @@ public class IntVector512Tests extends AbstractVectorTest { static long ADDReduceLong(int[] a, int idx) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6933,7 +6983,7 @@ public class IntVector512Tests extends AbstractVectorTest { static long ADDReduceAllLong(int[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((int)res, (int)ADDReduceLong(a, i)); } return res; @@ -6951,8 +7001,8 @@ public class IntVector512Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6962,8 +7012,9 @@ public class IntVector512Tests extends AbstractVectorTest { static long ADDReduceLongMasked(int[] a, int idx, boolean[] mask) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6972,7 +7023,7 @@ public class IntVector512Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(int[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((int)res, (int)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6992,8 +7043,8 @@ public class IntVector512Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/IntVector64Tests.java b/test/jdk/jdk/incubator/vector/IntVector64Tests.java index 0715981e050..9d3849a2c04 100644 --- a/test/jdk/jdk/incubator/vector/IntVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/IntVector64Tests.java @@ -1531,6 +1531,59 @@ public class IntVector64Tests extends AbstractVectorTest { return a >= b; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + + static int scalar_or(int a, int b) { + return (int)(a | b); + } + + static int scalar_and(int a, int b) { + return (int)(a & b); + } + + static int scalar_xor(int a, int b) { + return (int)(a ^ b); + } + + static int scalar_add(int a, int b) { + return (int)(a + b); + } + + static int scalar_sub(int a, int b) { + return (int)(a - b); + } + + static int scalar_mul(int a, int b) { + return (int)(a * b); + } + + static int scalar_min(int a, int b) { + return (int)(Math.min(a, b)); + } + + static int scalar_max(int a, int b) { + return (int)(Math.max(a, b)); + } + + static int scalar_div(int a, int b) { + return (int)(a / b); + } + + static int scalar_fma(int a, int b, int c) { + return (int)(Math.fma(a, b, c)); + } + + static int scalar_abs(int a) { + return (int)(Math.abs(a)); + } + + static int scalar_neg(int a) { + return ((int)-a); + } + + static boolean ult(int a, int b) { return Integer.compareUnsigned(a, b) < 0; } @@ -1547,9 +1600,6 @@ public class IntVector64Tests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } - static int firstNonZero(int a, int b) { - return Integer.compare(a, (int) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1663,7 +1713,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int ADD(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1684,7 +1734,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int add(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1741,7 +1791,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int SUB(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1762,7 +1812,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int sub(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1819,7 +1869,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int MUL(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1840,7 +1890,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int mul(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1987,7 +2037,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int FIRST_NONZERO(int a, int b) { - return (int)((a)!=0?a:b); + return (int)(firstNonZero(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3283,7 +3333,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int MIN(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3304,7 +3354,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int min(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3323,7 +3373,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int MAX(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3344,7 +3394,7 @@ public class IntVector64Tests extends AbstractVectorTest { } static int max(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3712,7 +3762,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ANDReduce(int[] a, int idx) { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3721,7 +3771,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ANDReduceAll(int[] a) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3739,7 +3789,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3752,20 +3802,20 @@ public class IntVector64Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = AND_IDENTITY; - assertEquals((int) (id & id), id, + assertEquals((int) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id & x), x); - assertEquals((int) (x & id), x); + assertEquals((int) (scalar_and(id, x)), x); + assertEquals((int) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id & x), x, + assertEquals((int) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x & id), x, + assertEquals((int) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3774,7 +3824,7 @@ public class IntVector64Tests extends AbstractVectorTest { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3783,7 +3833,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ANDReduceAllMasked(int[] a, boolean[] mask) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3803,7 +3853,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3814,7 +3864,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ORReduce(int[] a, int idx) { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3823,7 +3873,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ORReduceAll(int[] a) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3841,7 +3891,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3854,20 +3904,20 @@ public class IntVector64Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = OR_IDENTITY; - assertEquals((int) (id | id), id, + assertEquals((int) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id | x), x); - assertEquals((int) (x | id), x); + assertEquals((int) (scalar_or(id, x)), x); + assertEquals((int) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id | x), x, + assertEquals((int) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x | id), x, + assertEquals((int) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3876,7 +3926,7 @@ public class IntVector64Tests extends AbstractVectorTest { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3885,7 +3935,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ORReduceAllMasked(int[] a, boolean[] mask) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3905,7 +3955,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3916,7 +3966,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int XORReduce(int[] a, int idx) { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3925,7 +3975,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int XORReduceAll(int[] a) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3943,7 +3993,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3956,20 +4006,20 @@ public class IntVector64Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = XOR_IDENTITY; - assertEquals((int) (id ^ id), id, + assertEquals((int) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id ^ x), x); - assertEquals((int) (x ^ id), x); + assertEquals((int) (scalar_xor(id, x)), x); + assertEquals((int) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id ^ x), x, + assertEquals((int) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x ^ id), x, + assertEquals((int) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3978,7 +4028,7 @@ public class IntVector64Tests extends AbstractVectorTest { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3987,7 +4037,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int XORReduceAllMasked(int[] a, boolean[] mask) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4007,7 +4057,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4018,7 +4068,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ADDReduce(int[] a, int idx) { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4027,7 +4077,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ADDReduceAll(int[] a) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4045,7 +4095,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4058,20 +4108,20 @@ public class IntVector64Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = ADD_IDENTITY; - assertEquals((int) (id + id), id, + assertEquals((int) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id + x), x); - assertEquals((int) (x + id), x); + assertEquals((int) (scalar_add(id, x)), x); + assertEquals((int) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id + x), x, + assertEquals((int) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x + id), x, + assertEquals((int) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4080,7 +4130,7 @@ public class IntVector64Tests extends AbstractVectorTest { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4089,7 +4139,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int ADDReduceAllMasked(int[] a, boolean[] mask) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4109,7 +4159,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4120,7 +4170,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MULReduce(int[] a, int idx) { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4129,7 +4179,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MULReduceAll(int[] a) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4147,7 +4197,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4160,20 +4210,20 @@ public class IntVector64Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MUL_IDENTITY; - assertEquals((int) (id * id), id, + assertEquals((int) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id * x), x); - assertEquals((int) (x * id), x); + assertEquals((int) (scalar_mul(id, x)), x); + assertEquals((int) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id * x), x, + assertEquals((int) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x * id), x, + assertEquals((int) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4182,7 +4232,7 @@ public class IntVector64Tests extends AbstractVectorTest { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4191,7 +4241,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MULReduceAllMasked(int[] a, boolean[] mask) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4211,7 +4261,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4222,7 +4272,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4231,7 +4281,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4249,7 +4299,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4262,20 +4312,20 @@ public class IntVector64Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MIN_IDENTITY; - assertEquals((int) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.min(id, x), x); - assertEquals((int) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4284,7 +4334,7 @@ public class IntVector64Tests extends AbstractVectorTest { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4293,7 +4343,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4313,7 +4363,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4324,7 +4374,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4333,7 +4383,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4351,7 +4401,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4364,20 +4414,20 @@ public class IntVector64Tests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MAX_IDENTITY; - assertEquals((int) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.max(id, x), x); - assertEquals((int) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4386,7 +4436,7 @@ public class IntVector64Tests extends AbstractVectorTest { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4395,7 +4445,7 @@ public class IntVector64Tests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4415,7 +4465,7 @@ public class IntVector64Tests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5448,7 +5498,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5468,7 +5518,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5484,7 +5534,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (int)((long)b[i]))); } } } @@ -5504,7 +5554,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (int)((long)b[i])))); } } } @@ -5520,7 +5570,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5540,7 +5590,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5556,7 +5606,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (int)((long)b[i]))); } } } @@ -5576,7 +5626,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (int)((long)b[i])))); } } } @@ -6288,11 +6338,11 @@ public class IntVector64Tests extends AbstractVectorTest { } static int NEG(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } static int neg(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6344,11 +6394,11 @@ public class IntVector64Tests extends AbstractVectorTest { } static int ABS(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } static int abs(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6839,7 +6889,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6855,7 +6905,7 @@ public class IntVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6924,7 +6974,7 @@ public class IntVector64Tests extends AbstractVectorTest { static long ADDReduceLong(int[] a, int idx) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6933,7 +6983,7 @@ public class IntVector64Tests extends AbstractVectorTest { static long ADDReduceAllLong(int[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((int)res, (int)ADDReduceLong(a, i)); } return res; @@ -6951,8 +7001,8 @@ public class IntVector64Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6962,8 +7012,9 @@ public class IntVector64Tests extends AbstractVectorTest { static long ADDReduceLongMasked(int[] a, int idx, boolean[] mask) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6972,7 +7023,7 @@ public class IntVector64Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(int[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((int)res, (int)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6992,8 +7043,8 @@ public class IntVector64Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java b/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java index ad519b36dc9..6c671a81bf1 100644 --- a/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/IntVectorMaxTests.java @@ -1537,6 +1537,59 @@ public class IntVectorMaxTests extends AbstractVectorTest { return a >= b; } + static int firstNonZero(int a, int b) { + return Integer.compare(a, (int) 0) != 0 ? a : b; + } + + static int scalar_or(int a, int b) { + return (int)(a | b); + } + + static int scalar_and(int a, int b) { + return (int)(a & b); + } + + static int scalar_xor(int a, int b) { + return (int)(a ^ b); + } + + static int scalar_add(int a, int b) { + return (int)(a + b); + } + + static int scalar_sub(int a, int b) { + return (int)(a - b); + } + + static int scalar_mul(int a, int b) { + return (int)(a * b); + } + + static int scalar_min(int a, int b) { + return (int)(Math.min(a, b)); + } + + static int scalar_max(int a, int b) { + return (int)(Math.max(a, b)); + } + + static int scalar_div(int a, int b) { + return (int)(a / b); + } + + static int scalar_fma(int a, int b, int c) { + return (int)(Math.fma(a, b, c)); + } + + static int scalar_abs(int a) { + return (int)(Math.abs(a)); + } + + static int scalar_neg(int a) { + return ((int)-a); + } + + static boolean ult(int a, int b) { return Integer.compareUnsigned(a, b) < 0; } @@ -1553,9 +1606,6 @@ public class IntVectorMaxTests extends AbstractVectorTest { return Integer.compareUnsigned(a, b) >= 0; } - static int firstNonZero(int a, int b) { - return Integer.compare(a, (int) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1669,7 +1719,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int ADD(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1690,7 +1740,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int add(int a, int b) { - return (int)(a + b); + return (int)(scalar_add(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1747,7 +1797,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int SUB(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1768,7 +1818,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int sub(int a, int b) { - return (int)(a - b); + return (int)(scalar_sub(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1825,7 +1875,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int MUL(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1846,7 +1896,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int mul(int a, int b) { - return (int)(a * b); + return (int)(scalar_mul(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -1993,7 +2043,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int FIRST_NONZERO(int a, int b) { - return (int)((a)!=0?a:b); + return (int)(firstNonZero(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3289,7 +3339,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int MIN(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3310,7 +3360,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int min(int a, int b) { - return (int)(Math.min(a, b)); + return (int)(scalar_min(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3329,7 +3379,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int MAX(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3350,7 +3400,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int max(int a, int b) { - return (int)(Math.max(a, b)); + return (int)(scalar_max(a, b)); } @Test(dataProvider = "intBinaryOpProvider") @@ -3718,7 +3768,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ANDReduce(int[] a, int idx) { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3727,7 +3777,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ANDReduceAll(int[] a) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3745,7 +3795,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3758,20 +3808,20 @@ public class IntVectorMaxTests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = AND_IDENTITY; - assertEquals((int) (id & id), id, + assertEquals((int) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id & x), x); - assertEquals((int) (x & id), x); + assertEquals((int) (scalar_and(id, x)), x); + assertEquals((int) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id & x), x, + assertEquals((int) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x & id), x, + assertEquals((int) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3780,7 +3830,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { int res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3789,7 +3839,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ANDReduceAllMasked(int[] a, boolean[] mask) { int res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3809,7 +3859,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3820,7 +3870,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ORReduce(int[] a, int idx) { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3829,7 +3879,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ORReduceAll(int[] a) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3847,7 +3897,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3860,20 +3910,20 @@ public class IntVectorMaxTests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = OR_IDENTITY; - assertEquals((int) (id | id), id, + assertEquals((int) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id | x), x); - assertEquals((int) (x | id), x); + assertEquals((int) (scalar_or(id, x)), x); + assertEquals((int) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id | x), x, + assertEquals((int) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x | id), x, + assertEquals((int) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3882,7 +3932,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { int res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3891,7 +3941,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ORReduceAllMasked(int[] a, boolean[] mask) { int res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3911,7 +3961,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3922,7 +3972,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int XORReduce(int[] a, int idx) { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3931,7 +3981,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int XORReduceAll(int[] a) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3949,7 +3999,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3962,20 +4012,20 @@ public class IntVectorMaxTests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = XOR_IDENTITY; - assertEquals((int) (id ^ id), id, + assertEquals((int) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id ^ x), x); - assertEquals((int) (x ^ id), x); + assertEquals((int) (scalar_xor(id, x)), x); + assertEquals((int) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id ^ x), x, + assertEquals((int) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x ^ id), x, + assertEquals((int) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3984,7 +4034,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { int res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3993,7 +4043,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int XORReduceAllMasked(int[] a, boolean[] mask) { int res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4013,7 +4063,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4024,7 +4074,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ADDReduce(int[] a, int idx) { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4033,7 +4083,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ADDReduceAll(int[] a) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4051,7 +4101,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4064,20 +4114,20 @@ public class IntVectorMaxTests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = ADD_IDENTITY; - assertEquals((int) (id + id), id, + assertEquals((int) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id + x), x); - assertEquals((int) (x + id), x); + assertEquals((int) (scalar_add(id, x)), x); + assertEquals((int) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id + x), x, + assertEquals((int) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x + id), x, + assertEquals((int) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4086,7 +4136,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { int res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4095,7 +4145,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int ADDReduceAllMasked(int[] a, boolean[] mask) { int res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4115,7 +4165,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4126,7 +4176,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MULReduce(int[] a, int idx) { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4135,7 +4185,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MULReduceAll(int[] a) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4153,7 +4203,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4166,20 +4216,20 @@ public class IntVectorMaxTests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MUL_IDENTITY; - assertEquals((int) (id * id), id, + assertEquals((int) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) (id * x), x); - assertEquals((int) (x * id), x); + assertEquals((int) (scalar_mul(id, x)), x); + assertEquals((int) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((int) (id * x), x, + assertEquals((int) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((int) (x * id), x, + assertEquals((int) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4188,7 +4238,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { int res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4197,7 +4247,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MULReduceAllMasked(int[] a, boolean[] mask) { int res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4217,7 +4267,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4228,7 +4278,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MINReduce(int[] a, int idx) { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4237,7 +4287,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MINReduceAll(int[] a) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4255,7 +4305,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4268,20 +4318,20 @@ public class IntVectorMaxTests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MIN_IDENTITY; - assertEquals((int) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.min(id, x), x); - assertEquals((int) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4290,7 +4340,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { int res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4299,7 +4349,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MINReduceAllMasked(int[] a, boolean[] mask) { int res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4319,7 +4369,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (int) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4330,7 +4380,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MAXReduce(int[] a, int idx) { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4339,7 +4389,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MAXReduceAll(int[] a) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4357,7 +4407,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4370,20 +4420,20 @@ public class IntVectorMaxTests extends AbstractVectorTest { int[] a = fa.apply(SPECIES.length()); int id = MAX_IDENTITY; - assertEquals((int) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); int x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((int) Math.max(id, x), x); - assertEquals((int) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((int) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((int) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4392,7 +4442,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { int res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (int) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4401,7 +4451,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static int MAXReduceAllMasked(int[] a, boolean[] mask) { int res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (int) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4421,7 +4471,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { IntVector av = IntVector.fromArray(SPECIES, a, i); int v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (int) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5454,7 +5504,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5474,7 +5524,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5490,7 +5540,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (int)((long)b[i]))); } } } @@ -5510,7 +5560,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (int)((long)b[i])))); } } } @@ -5526,7 +5576,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5546,7 +5596,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5562,7 +5612,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (int)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (int)((long)b[i]))); } } } @@ -5582,7 +5632,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (int)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (int)((long)b[i])))); } } } @@ -6294,11 +6344,11 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int NEG(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } static int neg(int a) { - return (int)(-((int)a)); + return (int)(scalar_neg((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6350,11 +6400,11 @@ public class IntVectorMaxTests extends AbstractVectorTest { } static int ABS(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } static int abs(int a) { - return (int)(Math.abs((int)a)); + return (int)(scalar_abs((int)a)); } @Test(dataProvider = "intUnaryOpProvider") @@ -6845,7 +6895,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6861,7 +6911,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6930,7 +6980,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static long ADDReduceLong(int[] a, int idx) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6939,7 +6989,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static long ADDReduceAllLong(int[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((int)res, (int)ADDReduceLong(a, i)); } return res; @@ -6957,8 +7007,8 @@ public class IntVectorMaxTests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6968,8 +7018,9 @@ public class IntVectorMaxTests extends AbstractVectorTest { static long ADDReduceLongMasked(int[] a, int idx, boolean[] mask) { int res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6978,7 +7029,7 @@ public class IntVectorMaxTests extends AbstractVectorTest { static long ADDReduceAllLongMasked(int[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((int)res, (int)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6998,8 +7049,8 @@ public class IntVectorMaxTests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((int)ra, (int)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/LongVector128Tests.java b/test/jdk/jdk/incubator/vector/LongVector128Tests.java index 1d3af1684b9..49e2e1a0078 100644 --- a/test/jdk/jdk/incubator/vector/LongVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/LongVector128Tests.java @@ -1547,6 +1547,59 @@ public class LongVector128Tests extends AbstractVectorTest { return a >= b; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + + static long scalar_or(long a, long b) { + return (long)(a | b); + } + + static long scalar_and(long a, long b) { + return (long)(a & b); + } + + static long scalar_xor(long a, long b) { + return (long)(a ^ b); + } + + static long scalar_add(long a, long b) { + return (long)(a + b); + } + + static long scalar_sub(long a, long b) { + return (long)(a - b); + } + + static long scalar_mul(long a, long b) { + return (long)(a * b); + } + + static long scalar_min(long a, long b) { + return (long)(Math.min(a, b)); + } + + static long scalar_max(long a, long b) { + return (long)(Math.max(a, b)); + } + + static long scalar_div(long a, long b) { + return (long)(a / b); + } + + static long scalar_fma(long a, long b, long c) { + return (long)(Math.fma(a, b, c)); + } + + static long scalar_abs(long a) { + return (long)(Math.abs(a)); + } + + static long scalar_neg(long a) { + return ((long)-a); + } + + static boolean ult(long a, long b) { return Long.compareUnsigned(a, b) < 0; } @@ -1563,9 +1616,6 @@ public class LongVector128Tests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } - static long firstNonZero(long a, long b) { - return Long.compare(a, (long) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1679,7 +1729,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long ADD(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1700,7 +1750,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long add(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1757,7 +1807,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long SUB(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1778,7 +1828,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long sub(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1835,7 +1885,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long MUL(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1856,7 +1906,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long mul(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -2003,7 +2053,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long FIRST_NONZERO(long a, long b) { - return (long)((a)!=0?a:b); + return (long)(firstNonZero(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3299,7 +3349,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long MIN(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3320,7 +3370,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long min(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3339,7 +3389,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long MAX(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3360,7 +3410,7 @@ public class LongVector128Tests extends AbstractVectorTest { } static long max(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3728,7 +3778,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ANDReduce(long[] a, int idx) { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3737,7 +3787,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ANDReduceAll(long[] a) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3755,7 +3805,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3768,20 +3818,20 @@ public class LongVector128Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = AND_IDENTITY; - assertEquals((long) (id & id), id, + assertEquals((long) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id & x), x); - assertEquals((long) (x & id), x); + assertEquals((long) (scalar_and(id, x)), x); + assertEquals((long) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id & x), x, + assertEquals((long) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x & id), x, + assertEquals((long) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3790,7 +3840,7 @@ public class LongVector128Tests extends AbstractVectorTest { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3799,7 +3849,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ANDReduceAllMasked(long[] a, boolean[] mask) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3819,7 +3869,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3830,7 +3880,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ORReduce(long[] a, int idx) { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3839,7 +3889,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ORReduceAll(long[] a) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3857,7 +3907,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3870,20 +3920,20 @@ public class LongVector128Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = OR_IDENTITY; - assertEquals((long) (id | id), id, + assertEquals((long) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id | x), x); - assertEquals((long) (x | id), x); + assertEquals((long) (scalar_or(id, x)), x); + assertEquals((long) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id | x), x, + assertEquals((long) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x | id), x, + assertEquals((long) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3892,7 +3942,7 @@ public class LongVector128Tests extends AbstractVectorTest { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3901,7 +3951,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ORReduceAllMasked(long[] a, boolean[] mask) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3921,7 +3971,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3932,7 +3982,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long XORReduce(long[] a, int idx) { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3941,7 +3991,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long XORReduceAll(long[] a) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3959,7 +4009,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3972,20 +4022,20 @@ public class LongVector128Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = XOR_IDENTITY; - assertEquals((long) (id ^ id), id, + assertEquals((long) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id ^ x), x); - assertEquals((long) (x ^ id), x); + assertEquals((long) (scalar_xor(id, x)), x); + assertEquals((long) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id ^ x), x, + assertEquals((long) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x ^ id), x, + assertEquals((long) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3994,7 +4044,7 @@ public class LongVector128Tests extends AbstractVectorTest { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -4003,7 +4053,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long XORReduceAllMasked(long[] a, boolean[] mask) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4023,7 +4073,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4034,7 +4084,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ADDReduce(long[] a, int idx) { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4043,7 +4093,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ADDReduceAll(long[] a) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4061,7 +4111,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4074,20 +4124,20 @@ public class LongVector128Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = ADD_IDENTITY; - assertEquals((long) (id + id), id, + assertEquals((long) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id + x), x); - assertEquals((long) (x + id), x); + assertEquals((long) (scalar_add(id, x)), x); + assertEquals((long) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id + x), x, + assertEquals((long) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x + id), x, + assertEquals((long) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4096,7 +4146,7 @@ public class LongVector128Tests extends AbstractVectorTest { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4105,7 +4155,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long ADDReduceAllMasked(long[] a, boolean[] mask) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4125,7 +4175,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4136,7 +4186,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MULReduce(long[] a, int idx) { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4145,7 +4195,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MULReduceAll(long[] a) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4163,7 +4213,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4176,20 +4226,20 @@ public class LongVector128Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MUL_IDENTITY; - assertEquals((long) (id * id), id, + assertEquals((long) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id * x), x); - assertEquals((long) (x * id), x); + assertEquals((long) (scalar_mul(id, x)), x); + assertEquals((long) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id * x), x, + assertEquals((long) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x * id), x, + assertEquals((long) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4198,7 +4248,7 @@ public class LongVector128Tests extends AbstractVectorTest { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4207,7 +4257,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MULReduceAllMasked(long[] a, boolean[] mask) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4227,7 +4277,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4238,7 +4288,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4247,7 +4297,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4265,7 +4315,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4278,20 +4328,20 @@ public class LongVector128Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MIN_IDENTITY; - assertEquals((long) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.min(id, x), x); - assertEquals((long) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4300,7 +4350,7 @@ public class LongVector128Tests extends AbstractVectorTest { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4309,7 +4359,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4329,7 +4379,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4340,7 +4390,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4349,7 +4399,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4367,7 +4417,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4380,20 +4430,20 @@ public class LongVector128Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MAX_IDENTITY; - assertEquals((long) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.max(id, x), x); - assertEquals((long) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4402,7 +4452,7 @@ public class LongVector128Tests extends AbstractVectorTest { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4411,7 +4461,7 @@ public class LongVector128Tests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4431,7 +4481,7 @@ public class LongVector128Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5464,7 +5514,7 @@ public class LongVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5484,7 +5534,7 @@ public class LongVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5501,7 +5551,7 @@ public class LongVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5521,7 +5571,7 @@ public class LongVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -6234,11 +6284,11 @@ public class LongVector128Tests extends AbstractVectorTest { } static long NEG(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } static long neg(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6290,11 +6340,11 @@ public class LongVector128Tests extends AbstractVectorTest { } static long ABS(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } static long abs(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6785,7 +6835,7 @@ public class LongVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6801,7 +6851,7 @@ public class LongVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } diff --git a/test/jdk/jdk/incubator/vector/LongVector256Tests.java b/test/jdk/jdk/incubator/vector/LongVector256Tests.java index a766abe920f..84c8da4e800 100644 --- a/test/jdk/jdk/incubator/vector/LongVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/LongVector256Tests.java @@ -1547,6 +1547,59 @@ public class LongVector256Tests extends AbstractVectorTest { return a >= b; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + + static long scalar_or(long a, long b) { + return (long)(a | b); + } + + static long scalar_and(long a, long b) { + return (long)(a & b); + } + + static long scalar_xor(long a, long b) { + return (long)(a ^ b); + } + + static long scalar_add(long a, long b) { + return (long)(a + b); + } + + static long scalar_sub(long a, long b) { + return (long)(a - b); + } + + static long scalar_mul(long a, long b) { + return (long)(a * b); + } + + static long scalar_min(long a, long b) { + return (long)(Math.min(a, b)); + } + + static long scalar_max(long a, long b) { + return (long)(Math.max(a, b)); + } + + static long scalar_div(long a, long b) { + return (long)(a / b); + } + + static long scalar_fma(long a, long b, long c) { + return (long)(Math.fma(a, b, c)); + } + + static long scalar_abs(long a) { + return (long)(Math.abs(a)); + } + + static long scalar_neg(long a) { + return ((long)-a); + } + + static boolean ult(long a, long b) { return Long.compareUnsigned(a, b) < 0; } @@ -1563,9 +1616,6 @@ public class LongVector256Tests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } - static long firstNonZero(long a, long b) { - return Long.compare(a, (long) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1679,7 +1729,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long ADD(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1700,7 +1750,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long add(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1757,7 +1807,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long SUB(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1778,7 +1828,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long sub(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1835,7 +1885,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long MUL(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1856,7 +1906,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long mul(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -2003,7 +2053,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long FIRST_NONZERO(long a, long b) { - return (long)((a)!=0?a:b); + return (long)(firstNonZero(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3299,7 +3349,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long MIN(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3320,7 +3370,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long min(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3339,7 +3389,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long MAX(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3360,7 +3410,7 @@ public class LongVector256Tests extends AbstractVectorTest { } static long max(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3728,7 +3778,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ANDReduce(long[] a, int idx) { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3737,7 +3787,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ANDReduceAll(long[] a) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3755,7 +3805,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3768,20 +3818,20 @@ public class LongVector256Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = AND_IDENTITY; - assertEquals((long) (id & id), id, + assertEquals((long) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id & x), x); - assertEquals((long) (x & id), x); + assertEquals((long) (scalar_and(id, x)), x); + assertEquals((long) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id & x), x, + assertEquals((long) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x & id), x, + assertEquals((long) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3790,7 +3840,7 @@ public class LongVector256Tests extends AbstractVectorTest { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3799,7 +3849,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ANDReduceAllMasked(long[] a, boolean[] mask) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3819,7 +3869,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3830,7 +3880,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ORReduce(long[] a, int idx) { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3839,7 +3889,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ORReduceAll(long[] a) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3857,7 +3907,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3870,20 +3920,20 @@ public class LongVector256Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = OR_IDENTITY; - assertEquals((long) (id | id), id, + assertEquals((long) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id | x), x); - assertEquals((long) (x | id), x); + assertEquals((long) (scalar_or(id, x)), x); + assertEquals((long) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id | x), x, + assertEquals((long) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x | id), x, + assertEquals((long) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3892,7 +3942,7 @@ public class LongVector256Tests extends AbstractVectorTest { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3901,7 +3951,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ORReduceAllMasked(long[] a, boolean[] mask) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3921,7 +3971,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3932,7 +3982,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long XORReduce(long[] a, int idx) { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3941,7 +3991,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long XORReduceAll(long[] a) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3959,7 +4009,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3972,20 +4022,20 @@ public class LongVector256Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = XOR_IDENTITY; - assertEquals((long) (id ^ id), id, + assertEquals((long) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id ^ x), x); - assertEquals((long) (x ^ id), x); + assertEquals((long) (scalar_xor(id, x)), x); + assertEquals((long) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id ^ x), x, + assertEquals((long) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x ^ id), x, + assertEquals((long) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3994,7 +4044,7 @@ public class LongVector256Tests extends AbstractVectorTest { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -4003,7 +4053,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long XORReduceAllMasked(long[] a, boolean[] mask) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4023,7 +4073,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4034,7 +4084,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ADDReduce(long[] a, int idx) { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4043,7 +4093,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ADDReduceAll(long[] a) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4061,7 +4111,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4074,20 +4124,20 @@ public class LongVector256Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = ADD_IDENTITY; - assertEquals((long) (id + id), id, + assertEquals((long) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id + x), x); - assertEquals((long) (x + id), x); + assertEquals((long) (scalar_add(id, x)), x); + assertEquals((long) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id + x), x, + assertEquals((long) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x + id), x, + assertEquals((long) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4096,7 +4146,7 @@ public class LongVector256Tests extends AbstractVectorTest { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4105,7 +4155,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long ADDReduceAllMasked(long[] a, boolean[] mask) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4125,7 +4175,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4136,7 +4186,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MULReduce(long[] a, int idx) { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4145,7 +4195,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MULReduceAll(long[] a) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4163,7 +4213,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4176,20 +4226,20 @@ public class LongVector256Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MUL_IDENTITY; - assertEquals((long) (id * id), id, + assertEquals((long) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id * x), x); - assertEquals((long) (x * id), x); + assertEquals((long) (scalar_mul(id, x)), x); + assertEquals((long) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id * x), x, + assertEquals((long) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x * id), x, + assertEquals((long) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4198,7 +4248,7 @@ public class LongVector256Tests extends AbstractVectorTest { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4207,7 +4257,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MULReduceAllMasked(long[] a, boolean[] mask) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4227,7 +4277,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4238,7 +4288,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4247,7 +4297,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4265,7 +4315,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4278,20 +4328,20 @@ public class LongVector256Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MIN_IDENTITY; - assertEquals((long) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.min(id, x), x); - assertEquals((long) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4300,7 +4350,7 @@ public class LongVector256Tests extends AbstractVectorTest { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4309,7 +4359,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4329,7 +4379,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4340,7 +4390,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4349,7 +4399,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4367,7 +4417,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4380,20 +4430,20 @@ public class LongVector256Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MAX_IDENTITY; - assertEquals((long) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.max(id, x), x); - assertEquals((long) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4402,7 +4452,7 @@ public class LongVector256Tests extends AbstractVectorTest { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4411,7 +4461,7 @@ public class LongVector256Tests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4431,7 +4481,7 @@ public class LongVector256Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5464,7 +5514,7 @@ public class LongVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5484,7 +5534,7 @@ public class LongVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5501,7 +5551,7 @@ public class LongVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5521,7 +5571,7 @@ public class LongVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -6234,11 +6284,11 @@ public class LongVector256Tests extends AbstractVectorTest { } static long NEG(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } static long neg(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6290,11 +6340,11 @@ public class LongVector256Tests extends AbstractVectorTest { } static long ABS(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } static long abs(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6785,7 +6835,7 @@ public class LongVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6801,7 +6851,7 @@ public class LongVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } diff --git a/test/jdk/jdk/incubator/vector/LongVector512Tests.java b/test/jdk/jdk/incubator/vector/LongVector512Tests.java index 503bd7942f2..00d8c4b010a 100644 --- a/test/jdk/jdk/incubator/vector/LongVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/LongVector512Tests.java @@ -1547,6 +1547,59 @@ public class LongVector512Tests extends AbstractVectorTest { return a >= b; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + + static long scalar_or(long a, long b) { + return (long)(a | b); + } + + static long scalar_and(long a, long b) { + return (long)(a & b); + } + + static long scalar_xor(long a, long b) { + return (long)(a ^ b); + } + + static long scalar_add(long a, long b) { + return (long)(a + b); + } + + static long scalar_sub(long a, long b) { + return (long)(a - b); + } + + static long scalar_mul(long a, long b) { + return (long)(a * b); + } + + static long scalar_min(long a, long b) { + return (long)(Math.min(a, b)); + } + + static long scalar_max(long a, long b) { + return (long)(Math.max(a, b)); + } + + static long scalar_div(long a, long b) { + return (long)(a / b); + } + + static long scalar_fma(long a, long b, long c) { + return (long)(Math.fma(a, b, c)); + } + + static long scalar_abs(long a) { + return (long)(Math.abs(a)); + } + + static long scalar_neg(long a) { + return ((long)-a); + } + + static boolean ult(long a, long b) { return Long.compareUnsigned(a, b) < 0; } @@ -1563,9 +1616,6 @@ public class LongVector512Tests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } - static long firstNonZero(long a, long b) { - return Long.compare(a, (long) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1679,7 +1729,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long ADD(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1700,7 +1750,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long add(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1757,7 +1807,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long SUB(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1778,7 +1828,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long sub(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1835,7 +1885,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long MUL(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1856,7 +1906,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long mul(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -2003,7 +2053,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long FIRST_NONZERO(long a, long b) { - return (long)((a)!=0?a:b); + return (long)(firstNonZero(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3299,7 +3349,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long MIN(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3320,7 +3370,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long min(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3339,7 +3389,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long MAX(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3360,7 +3410,7 @@ public class LongVector512Tests extends AbstractVectorTest { } static long max(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3728,7 +3778,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ANDReduce(long[] a, int idx) { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3737,7 +3787,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ANDReduceAll(long[] a) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3755,7 +3805,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3768,20 +3818,20 @@ public class LongVector512Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = AND_IDENTITY; - assertEquals((long) (id & id), id, + assertEquals((long) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id & x), x); - assertEquals((long) (x & id), x); + assertEquals((long) (scalar_and(id, x)), x); + assertEquals((long) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id & x), x, + assertEquals((long) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x & id), x, + assertEquals((long) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3790,7 +3840,7 @@ public class LongVector512Tests extends AbstractVectorTest { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3799,7 +3849,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ANDReduceAllMasked(long[] a, boolean[] mask) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3819,7 +3869,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3830,7 +3880,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ORReduce(long[] a, int idx) { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3839,7 +3889,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ORReduceAll(long[] a) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3857,7 +3907,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3870,20 +3920,20 @@ public class LongVector512Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = OR_IDENTITY; - assertEquals((long) (id | id), id, + assertEquals((long) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id | x), x); - assertEquals((long) (x | id), x); + assertEquals((long) (scalar_or(id, x)), x); + assertEquals((long) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id | x), x, + assertEquals((long) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x | id), x, + assertEquals((long) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3892,7 +3942,7 @@ public class LongVector512Tests extends AbstractVectorTest { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3901,7 +3951,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ORReduceAllMasked(long[] a, boolean[] mask) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3921,7 +3971,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3932,7 +3982,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long XORReduce(long[] a, int idx) { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3941,7 +3991,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long XORReduceAll(long[] a) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3959,7 +4009,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3972,20 +4022,20 @@ public class LongVector512Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = XOR_IDENTITY; - assertEquals((long) (id ^ id), id, + assertEquals((long) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id ^ x), x); - assertEquals((long) (x ^ id), x); + assertEquals((long) (scalar_xor(id, x)), x); + assertEquals((long) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id ^ x), x, + assertEquals((long) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x ^ id), x, + assertEquals((long) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3994,7 +4044,7 @@ public class LongVector512Tests extends AbstractVectorTest { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -4003,7 +4053,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long XORReduceAllMasked(long[] a, boolean[] mask) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4023,7 +4073,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4034,7 +4084,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ADDReduce(long[] a, int idx) { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4043,7 +4093,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ADDReduceAll(long[] a) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4061,7 +4111,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4074,20 +4124,20 @@ public class LongVector512Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = ADD_IDENTITY; - assertEquals((long) (id + id), id, + assertEquals((long) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id + x), x); - assertEquals((long) (x + id), x); + assertEquals((long) (scalar_add(id, x)), x); + assertEquals((long) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id + x), x, + assertEquals((long) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x + id), x, + assertEquals((long) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4096,7 +4146,7 @@ public class LongVector512Tests extends AbstractVectorTest { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4105,7 +4155,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long ADDReduceAllMasked(long[] a, boolean[] mask) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4125,7 +4175,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4136,7 +4186,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MULReduce(long[] a, int idx) { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4145,7 +4195,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MULReduceAll(long[] a) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4163,7 +4213,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4176,20 +4226,20 @@ public class LongVector512Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MUL_IDENTITY; - assertEquals((long) (id * id), id, + assertEquals((long) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id * x), x); - assertEquals((long) (x * id), x); + assertEquals((long) (scalar_mul(id, x)), x); + assertEquals((long) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id * x), x, + assertEquals((long) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x * id), x, + assertEquals((long) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4198,7 +4248,7 @@ public class LongVector512Tests extends AbstractVectorTest { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4207,7 +4257,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MULReduceAllMasked(long[] a, boolean[] mask) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4227,7 +4277,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4238,7 +4288,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4247,7 +4297,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4265,7 +4315,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4278,20 +4328,20 @@ public class LongVector512Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MIN_IDENTITY; - assertEquals((long) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.min(id, x), x); - assertEquals((long) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4300,7 +4350,7 @@ public class LongVector512Tests extends AbstractVectorTest { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4309,7 +4359,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4329,7 +4379,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4340,7 +4390,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4349,7 +4399,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4367,7 +4417,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4380,20 +4430,20 @@ public class LongVector512Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MAX_IDENTITY; - assertEquals((long) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.max(id, x), x); - assertEquals((long) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4402,7 +4452,7 @@ public class LongVector512Tests extends AbstractVectorTest { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4411,7 +4461,7 @@ public class LongVector512Tests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4431,7 +4481,7 @@ public class LongVector512Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5464,7 +5514,7 @@ public class LongVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5484,7 +5534,7 @@ public class LongVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5501,7 +5551,7 @@ public class LongVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5521,7 +5571,7 @@ public class LongVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -6234,11 +6284,11 @@ public class LongVector512Tests extends AbstractVectorTest { } static long NEG(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } static long neg(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6290,11 +6340,11 @@ public class LongVector512Tests extends AbstractVectorTest { } static long ABS(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } static long abs(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6785,7 +6835,7 @@ public class LongVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6801,7 +6851,7 @@ public class LongVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } diff --git a/test/jdk/jdk/incubator/vector/LongVector64Tests.java b/test/jdk/jdk/incubator/vector/LongVector64Tests.java index 6ca3c63054a..d4cdfe54ad2 100644 --- a/test/jdk/jdk/incubator/vector/LongVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/LongVector64Tests.java @@ -1547,6 +1547,59 @@ public class LongVector64Tests extends AbstractVectorTest { return a >= b; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + + static long scalar_or(long a, long b) { + return (long)(a | b); + } + + static long scalar_and(long a, long b) { + return (long)(a & b); + } + + static long scalar_xor(long a, long b) { + return (long)(a ^ b); + } + + static long scalar_add(long a, long b) { + return (long)(a + b); + } + + static long scalar_sub(long a, long b) { + return (long)(a - b); + } + + static long scalar_mul(long a, long b) { + return (long)(a * b); + } + + static long scalar_min(long a, long b) { + return (long)(Math.min(a, b)); + } + + static long scalar_max(long a, long b) { + return (long)(Math.max(a, b)); + } + + static long scalar_div(long a, long b) { + return (long)(a / b); + } + + static long scalar_fma(long a, long b, long c) { + return (long)(Math.fma(a, b, c)); + } + + static long scalar_abs(long a) { + return (long)(Math.abs(a)); + } + + static long scalar_neg(long a) { + return ((long)-a); + } + + static boolean ult(long a, long b) { return Long.compareUnsigned(a, b) < 0; } @@ -1563,9 +1616,6 @@ public class LongVector64Tests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } - static long firstNonZero(long a, long b) { - return Long.compare(a, (long) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1679,7 +1729,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long ADD(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1700,7 +1750,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long add(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1757,7 +1807,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long SUB(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1778,7 +1828,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long sub(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1835,7 +1885,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long MUL(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1856,7 +1906,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long mul(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -2003,7 +2053,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long FIRST_NONZERO(long a, long b) { - return (long)((a)!=0?a:b); + return (long)(firstNonZero(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3299,7 +3349,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long MIN(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3320,7 +3370,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long min(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3339,7 +3389,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long MAX(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3360,7 +3410,7 @@ public class LongVector64Tests extends AbstractVectorTest { } static long max(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3728,7 +3778,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ANDReduce(long[] a, int idx) { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3737,7 +3787,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ANDReduceAll(long[] a) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3755,7 +3805,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3768,20 +3818,20 @@ public class LongVector64Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = AND_IDENTITY; - assertEquals((long) (id & id), id, + assertEquals((long) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id & x), x); - assertEquals((long) (x & id), x); + assertEquals((long) (scalar_and(id, x)), x); + assertEquals((long) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id & x), x, + assertEquals((long) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x & id), x, + assertEquals((long) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3790,7 +3840,7 @@ public class LongVector64Tests extends AbstractVectorTest { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3799,7 +3849,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ANDReduceAllMasked(long[] a, boolean[] mask) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3819,7 +3869,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3830,7 +3880,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ORReduce(long[] a, int idx) { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3839,7 +3889,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ORReduceAll(long[] a) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3857,7 +3907,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3870,20 +3920,20 @@ public class LongVector64Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = OR_IDENTITY; - assertEquals((long) (id | id), id, + assertEquals((long) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id | x), x); - assertEquals((long) (x | id), x); + assertEquals((long) (scalar_or(id, x)), x); + assertEquals((long) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id | x), x, + assertEquals((long) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x | id), x, + assertEquals((long) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3892,7 +3942,7 @@ public class LongVector64Tests extends AbstractVectorTest { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3901,7 +3951,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ORReduceAllMasked(long[] a, boolean[] mask) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3921,7 +3971,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3932,7 +3982,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long XORReduce(long[] a, int idx) { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3941,7 +3991,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long XORReduceAll(long[] a) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3959,7 +4009,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3972,20 +4022,20 @@ public class LongVector64Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = XOR_IDENTITY; - assertEquals((long) (id ^ id), id, + assertEquals((long) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id ^ x), x); - assertEquals((long) (x ^ id), x); + assertEquals((long) (scalar_xor(id, x)), x); + assertEquals((long) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id ^ x), x, + assertEquals((long) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x ^ id), x, + assertEquals((long) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3994,7 +4044,7 @@ public class LongVector64Tests extends AbstractVectorTest { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -4003,7 +4053,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long XORReduceAllMasked(long[] a, boolean[] mask) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4023,7 +4073,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4034,7 +4084,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ADDReduce(long[] a, int idx) { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4043,7 +4093,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ADDReduceAll(long[] a) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4061,7 +4111,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4074,20 +4124,20 @@ public class LongVector64Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = ADD_IDENTITY; - assertEquals((long) (id + id), id, + assertEquals((long) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id + x), x); - assertEquals((long) (x + id), x); + assertEquals((long) (scalar_add(id, x)), x); + assertEquals((long) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id + x), x, + assertEquals((long) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x + id), x, + assertEquals((long) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4096,7 +4146,7 @@ public class LongVector64Tests extends AbstractVectorTest { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4105,7 +4155,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long ADDReduceAllMasked(long[] a, boolean[] mask) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4125,7 +4175,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4136,7 +4186,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MULReduce(long[] a, int idx) { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4145,7 +4195,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MULReduceAll(long[] a) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4163,7 +4213,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4176,20 +4226,20 @@ public class LongVector64Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MUL_IDENTITY; - assertEquals((long) (id * id), id, + assertEquals((long) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id * x), x); - assertEquals((long) (x * id), x); + assertEquals((long) (scalar_mul(id, x)), x); + assertEquals((long) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id * x), x, + assertEquals((long) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x * id), x, + assertEquals((long) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4198,7 +4248,7 @@ public class LongVector64Tests extends AbstractVectorTest { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4207,7 +4257,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MULReduceAllMasked(long[] a, boolean[] mask) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4227,7 +4277,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4238,7 +4288,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4247,7 +4297,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4265,7 +4315,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4278,20 +4328,20 @@ public class LongVector64Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MIN_IDENTITY; - assertEquals((long) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.min(id, x), x); - assertEquals((long) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4300,7 +4350,7 @@ public class LongVector64Tests extends AbstractVectorTest { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4309,7 +4359,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4329,7 +4379,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4340,7 +4390,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4349,7 +4399,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4367,7 +4417,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4380,20 +4430,20 @@ public class LongVector64Tests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MAX_IDENTITY; - assertEquals((long) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.max(id, x), x); - assertEquals((long) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4402,7 +4452,7 @@ public class LongVector64Tests extends AbstractVectorTest { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4411,7 +4461,7 @@ public class LongVector64Tests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4431,7 +4481,7 @@ public class LongVector64Tests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5464,7 +5514,7 @@ public class LongVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5484,7 +5534,7 @@ public class LongVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5501,7 +5551,7 @@ public class LongVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5521,7 +5571,7 @@ public class LongVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -6234,11 +6284,11 @@ public class LongVector64Tests extends AbstractVectorTest { } static long NEG(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } static long neg(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6290,11 +6340,11 @@ public class LongVector64Tests extends AbstractVectorTest { } static long ABS(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } static long abs(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6785,7 +6835,7 @@ public class LongVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6801,7 +6851,7 @@ public class LongVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } diff --git a/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java b/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java index aef89af5893..597169b00f5 100644 --- a/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/LongVectorMaxTests.java @@ -1553,6 +1553,59 @@ public class LongVectorMaxTests extends AbstractVectorTest { return a >= b; } + static long firstNonZero(long a, long b) { + return Long.compare(a, (long) 0) != 0 ? a : b; + } + + static long scalar_or(long a, long b) { + return (long)(a | b); + } + + static long scalar_and(long a, long b) { + return (long)(a & b); + } + + static long scalar_xor(long a, long b) { + return (long)(a ^ b); + } + + static long scalar_add(long a, long b) { + return (long)(a + b); + } + + static long scalar_sub(long a, long b) { + return (long)(a - b); + } + + static long scalar_mul(long a, long b) { + return (long)(a * b); + } + + static long scalar_min(long a, long b) { + return (long)(Math.min(a, b)); + } + + static long scalar_max(long a, long b) { + return (long)(Math.max(a, b)); + } + + static long scalar_div(long a, long b) { + return (long)(a / b); + } + + static long scalar_fma(long a, long b, long c) { + return (long)(Math.fma(a, b, c)); + } + + static long scalar_abs(long a) { + return (long)(Math.abs(a)); + } + + static long scalar_neg(long a) { + return ((long)-a); + } + + static boolean ult(long a, long b) { return Long.compareUnsigned(a, b) < 0; } @@ -1569,9 +1622,6 @@ public class LongVectorMaxTests extends AbstractVectorTest { return Long.compareUnsigned(a, b) >= 0; } - static long firstNonZero(long a, long b) { - return Long.compare(a, (long) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1685,7 +1735,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long ADD(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1706,7 +1756,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long add(long a, long b) { - return (long)(a + b); + return (long)(scalar_add(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1763,7 +1813,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long SUB(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1784,7 +1834,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long sub(long a, long b) { - return (long)(a - b); + return (long)(scalar_sub(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1841,7 +1891,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long MUL(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -1862,7 +1912,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long mul(long a, long b) { - return (long)(a * b); + return (long)(scalar_mul(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -2009,7 +2059,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long FIRST_NONZERO(long a, long b) { - return (long)((a)!=0?a:b); + return (long)(firstNonZero(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3305,7 +3355,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long MIN(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3326,7 +3376,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long min(long a, long b) { - return (long)(Math.min(a, b)); + return (long)(scalar_min(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3345,7 +3395,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long MAX(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3366,7 +3416,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long max(long a, long b) { - return (long)(Math.max(a, b)); + return (long)(scalar_max(a, b)); } @Test(dataProvider = "longBinaryOpProvider") @@ -3734,7 +3784,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ANDReduce(long[] a, int idx) { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3743,7 +3793,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ANDReduceAll(long[] a) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3761,7 +3811,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3774,20 +3824,20 @@ public class LongVectorMaxTests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = AND_IDENTITY; - assertEquals((long) (id & id), id, + assertEquals((long) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id & x), x); - assertEquals((long) (x & id), x); + assertEquals((long) (scalar_and(id, x)), x); + assertEquals((long) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id & x), x, + assertEquals((long) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x & id), x, + assertEquals((long) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3796,7 +3846,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { long res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3805,7 +3855,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ANDReduceAllMasked(long[] a, boolean[] mask) { long res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3825,7 +3875,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3836,7 +3886,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ORReduce(long[] a, int idx) { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3845,7 +3895,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ORReduceAll(long[] a) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3863,7 +3913,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3876,20 +3926,20 @@ public class LongVectorMaxTests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = OR_IDENTITY; - assertEquals((long) (id | id), id, + assertEquals((long) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id | x), x); - assertEquals((long) (x | id), x); + assertEquals((long) (scalar_or(id, x)), x); + assertEquals((long) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id | x), x, + assertEquals((long) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x | id), x, + assertEquals((long) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3898,7 +3948,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { long res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3907,7 +3957,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ORReduceAllMasked(long[] a, boolean[] mask) { long res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3927,7 +3977,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3938,7 +3988,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long XORReduce(long[] a, int idx) { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3947,7 +3997,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long XORReduceAll(long[] a) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3965,7 +4015,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3978,20 +4028,20 @@ public class LongVectorMaxTests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = XOR_IDENTITY; - assertEquals((long) (id ^ id), id, + assertEquals((long) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id ^ x), x); - assertEquals((long) (x ^ id), x); + assertEquals((long) (scalar_xor(id, x)), x); + assertEquals((long) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id ^ x), x, + assertEquals((long) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x ^ id), x, + assertEquals((long) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -4000,7 +4050,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { long res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -4009,7 +4059,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long XORReduceAllMasked(long[] a, boolean[] mask) { long res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -4029,7 +4079,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -4040,7 +4090,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ADDReduce(long[] a, int idx) { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4049,7 +4099,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ADDReduceAll(long[] a) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -4067,7 +4117,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4080,20 +4130,20 @@ public class LongVectorMaxTests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = ADD_IDENTITY; - assertEquals((long) (id + id), id, + assertEquals((long) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id + x), x); - assertEquals((long) (x + id), x); + assertEquals((long) (scalar_add(id, x)), x); + assertEquals((long) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id + x), x, + assertEquals((long) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x + id), x, + assertEquals((long) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4102,7 +4152,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { long res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4111,7 +4161,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long ADDReduceAllMasked(long[] a, boolean[] mask) { long res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4131,7 +4181,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4142,7 +4192,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MULReduce(long[] a, int idx) { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4151,7 +4201,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MULReduceAll(long[] a) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4169,7 +4219,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4182,20 +4232,20 @@ public class LongVectorMaxTests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MUL_IDENTITY; - assertEquals((long) (id * id), id, + assertEquals((long) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) (id * x), x); - assertEquals((long) (x * id), x); + assertEquals((long) (scalar_mul(id, x)), x); + assertEquals((long) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((long) (id * x), x, + assertEquals((long) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((long) (x * id), x, + assertEquals((long) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4204,7 +4254,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { long res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4213,7 +4263,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MULReduceAllMasked(long[] a, boolean[] mask) { long res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4233,7 +4283,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4244,7 +4294,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MINReduce(long[] a, int idx) { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4253,7 +4303,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MINReduceAll(long[] a) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4271,7 +4321,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4284,20 +4334,20 @@ public class LongVectorMaxTests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MIN_IDENTITY; - assertEquals((long) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.min(id, x), x); - assertEquals((long) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4306,7 +4356,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { long res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4315,7 +4365,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MINReduceAllMasked(long[] a, boolean[] mask) { long res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4335,7 +4385,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (long) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4346,7 +4396,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MAXReduce(long[] a, int idx) { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4355,7 +4405,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MAXReduceAll(long[] a) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4373,7 +4423,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4386,20 +4436,20 @@ public class LongVectorMaxTests extends AbstractVectorTest { long[] a = fa.apply(SPECIES.length()); long id = MAX_IDENTITY; - assertEquals((long) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); long x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((long) Math.max(id, x), x); - assertEquals((long) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((long) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((long) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4408,7 +4458,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { long res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (long) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4417,7 +4467,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { static long MAXReduceAllMasked(long[] a, boolean[] mask) { long res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (long) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4437,7 +4487,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { LongVector av = LongVector.fromArray(SPECIES, a, i); long v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (long) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5470,7 +5520,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5490,7 +5540,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5507,7 +5557,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5527,7 +5577,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -6240,11 +6290,11 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long NEG(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } static long neg(long a) { - return (long)(-((long)a)); + return (long)(scalar_neg((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6296,11 +6346,11 @@ public class LongVectorMaxTests extends AbstractVectorTest { } static long ABS(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } static long abs(long a) { - return (long)(Math.abs((long)a)); + return (long)(scalar_abs((long)a)); } @Test(dataProvider = "longUnaryOpProvider") @@ -6791,7 +6841,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6807,7 +6857,7 @@ public class LongVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } diff --git a/test/jdk/jdk/incubator/vector/ShortVector128Tests.java b/test/jdk/jdk/incubator/vector/ShortVector128Tests.java index 7cf49513620..85e7d715182 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector128Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector128Tests.java @@ -1565,6 +1565,59 @@ public class ShortVector128Tests extends AbstractVectorTest { return a >= b; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + + static short scalar_or(short a, short b) { + return (short)(a | b); + } + + static short scalar_and(short a, short b) { + return (short)(a & b); + } + + static short scalar_xor(short a, short b) { + return (short)(a ^ b); + } + + static short scalar_add(short a, short b) { + return (short)(a + b); + } + + static short scalar_sub(short a, short b) { + return (short)(a - b); + } + + static short scalar_mul(short a, short b) { + return (short)(a * b); + } + + static short scalar_min(short a, short b) { + return (short)(Math.min(a, b)); + } + + static short scalar_max(short a, short b) { + return (short)(Math.max(a, b)); + } + + static short scalar_div(short a, short b) { + return (short)(a / b); + } + + static short scalar_fma(short a, short b, short c) { + return (short)(Math.fma(a, b, c)); + } + + static short scalar_abs(short a) { + return (short)(Math.abs(a)); + } + + static short scalar_neg(short a) { + return ((short)-a); + } + + static boolean ult(short a, short b) { return Short.compareUnsigned(a, b) < 0; } @@ -1581,9 +1634,6 @@ public class ShortVector128Tests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } - static short firstNonZero(short a, short b) { - return Short.compare(a, (short) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1692,7 +1742,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short ADD(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1713,7 +1763,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short add(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1770,7 +1820,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short SUB(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1791,7 +1841,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short sub(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1848,7 +1898,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short MUL(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1869,7 +1919,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short mul(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -2016,7 +2066,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short FIRST_NONZERO(short a, short b) { - return (short)((a)!=0?a:b); + return (short)(firstNonZero(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3230,7 +3280,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short MIN(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3251,7 +3301,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short min(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3270,7 +3320,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short MAX(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3291,7 +3341,7 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short max(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3659,7 +3709,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ANDReduce(short[] a, int idx) { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3668,7 +3718,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ANDReduceAll(short[] a) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3686,7 +3736,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3699,20 +3749,20 @@ public class ShortVector128Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = AND_IDENTITY; - assertEquals((short) (id & id), id, + assertEquals((short) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id & x), x); - assertEquals((short) (x & id), x); + assertEquals((short) (scalar_and(id, x)), x); + assertEquals((short) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id & x), x, + assertEquals((short) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x & id), x, + assertEquals((short) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3721,7 +3771,7 @@ public class ShortVector128Tests extends AbstractVectorTest { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3730,7 +3780,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ANDReduceAllMasked(short[] a, boolean[] mask) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3750,7 +3800,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3761,7 +3811,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ORReduce(short[] a, int idx) { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3770,7 +3820,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ORReduceAll(short[] a) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3788,7 +3838,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3801,20 +3851,20 @@ public class ShortVector128Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = OR_IDENTITY; - assertEquals((short) (id | id), id, + assertEquals((short) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id | x), x); - assertEquals((short) (x | id), x); + assertEquals((short) (scalar_or(id, x)), x); + assertEquals((short) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id | x), x, + assertEquals((short) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x | id), x, + assertEquals((short) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3823,7 +3873,7 @@ public class ShortVector128Tests extends AbstractVectorTest { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3832,7 +3882,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ORReduceAllMasked(short[] a, boolean[] mask) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3852,7 +3902,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3863,7 +3913,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short XORReduce(short[] a, int idx) { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3872,7 +3922,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short XORReduceAll(short[] a) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3890,7 +3940,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3903,20 +3953,20 @@ public class ShortVector128Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = XOR_IDENTITY; - assertEquals((short) (id ^ id), id, + assertEquals((short) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id ^ x), x); - assertEquals((short) (x ^ id), x); + assertEquals((short) (scalar_xor(id, x)), x); + assertEquals((short) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id ^ x), x, + assertEquals((short) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x ^ id), x, + assertEquals((short) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3925,7 +3975,7 @@ public class ShortVector128Tests extends AbstractVectorTest { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3934,7 +3984,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short XORReduceAllMasked(short[] a, boolean[] mask) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3954,7 +4004,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3965,7 +4015,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ADDReduce(short[] a, int idx) { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3974,7 +4024,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ADDReduceAll(short[] a) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -3992,7 +4042,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4005,20 +4055,20 @@ public class ShortVector128Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = ADD_IDENTITY; - assertEquals((short) (id + id), id, + assertEquals((short) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id + x), x); - assertEquals((short) (x + id), x); + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id + x), x, + assertEquals((short) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x + id), x, + assertEquals((short) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4027,7 +4077,7 @@ public class ShortVector128Tests extends AbstractVectorTest { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4036,7 +4086,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short ADDReduceAllMasked(short[] a, boolean[] mask) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4056,7 +4106,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4067,7 +4117,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MULReduce(short[] a, int idx) { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4076,7 +4126,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MULReduceAll(short[] a) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4094,7 +4144,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4107,20 +4157,20 @@ public class ShortVector128Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MUL_IDENTITY; - assertEquals((short) (id * id), id, + assertEquals((short) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id * x), x); - assertEquals((short) (x * id), x); + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id * x), x, + assertEquals((short) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x * id), x, + assertEquals((short) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4129,7 +4179,7 @@ public class ShortVector128Tests extends AbstractVectorTest { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4138,7 +4188,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MULReduceAllMasked(short[] a, boolean[] mask) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4158,7 +4208,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4169,7 +4219,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4178,7 +4228,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4196,7 +4246,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4209,20 +4259,20 @@ public class ShortVector128Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MIN_IDENTITY; - assertEquals((short) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.min(id, x), x); - assertEquals((short) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4231,7 +4281,7 @@ public class ShortVector128Tests extends AbstractVectorTest { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4240,7 +4290,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4260,7 +4310,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4271,7 +4321,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4280,7 +4330,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4298,7 +4348,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4311,20 +4361,20 @@ public class ShortVector128Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MAX_IDENTITY; - assertEquals((short) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.max(id, x), x); - assertEquals((short) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4333,7 +4383,7 @@ public class ShortVector128Tests extends AbstractVectorTest { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4342,7 +4392,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4362,7 +4412,7 @@ public class ShortVector128Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5395,7 +5445,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5415,7 +5465,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5431,7 +5481,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (short)((long)b[i]))); } } } @@ -5451,7 +5501,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (short)((long)b[i])))); } } } @@ -5467,7 +5517,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5487,7 +5537,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5503,7 +5553,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (short)((long)b[i]))); } } } @@ -5523,7 +5573,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (short)((long)b[i])))); } } } @@ -6235,11 +6285,11 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short NEG(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } static short neg(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6291,11 +6341,11 @@ public class ShortVector128Tests extends AbstractVectorTest { } static short ABS(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } static short abs(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6786,7 +6836,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6802,7 +6852,7 @@ public class ShortVector128Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6871,7 +6921,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static long ADDReduceLong(short[] a, int idx) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6880,7 +6930,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static long ADDReduceAllLong(short[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); } return res; @@ -6898,8 +6948,8 @@ public class ShortVector128Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6909,8 +6959,9 @@ public class ShortVector128Tests extends AbstractVectorTest { static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6919,7 +6970,7 @@ public class ShortVector128Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6939,8 +6990,8 @@ public class ShortVector128Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ShortVector256Tests.java b/test/jdk/jdk/incubator/vector/ShortVector256Tests.java index 5104e3724f7..df379b64e3a 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector256Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector256Tests.java @@ -1565,6 +1565,59 @@ public class ShortVector256Tests extends AbstractVectorTest { return a >= b; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + + static short scalar_or(short a, short b) { + return (short)(a | b); + } + + static short scalar_and(short a, short b) { + return (short)(a & b); + } + + static short scalar_xor(short a, short b) { + return (short)(a ^ b); + } + + static short scalar_add(short a, short b) { + return (short)(a + b); + } + + static short scalar_sub(short a, short b) { + return (short)(a - b); + } + + static short scalar_mul(short a, short b) { + return (short)(a * b); + } + + static short scalar_min(short a, short b) { + return (short)(Math.min(a, b)); + } + + static short scalar_max(short a, short b) { + return (short)(Math.max(a, b)); + } + + static short scalar_div(short a, short b) { + return (short)(a / b); + } + + static short scalar_fma(short a, short b, short c) { + return (short)(Math.fma(a, b, c)); + } + + static short scalar_abs(short a) { + return (short)(Math.abs(a)); + } + + static short scalar_neg(short a) { + return ((short)-a); + } + + static boolean ult(short a, short b) { return Short.compareUnsigned(a, b) < 0; } @@ -1581,9 +1634,6 @@ public class ShortVector256Tests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } - static short firstNonZero(short a, short b) { - return Short.compare(a, (short) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1692,7 +1742,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short ADD(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1713,7 +1763,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short add(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1770,7 +1820,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short SUB(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1791,7 +1841,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short sub(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1848,7 +1898,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short MUL(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1869,7 +1919,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short mul(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -2016,7 +2066,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short FIRST_NONZERO(short a, short b) { - return (short)((a)!=0?a:b); + return (short)(firstNonZero(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3230,7 +3280,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short MIN(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3251,7 +3301,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short min(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3270,7 +3320,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short MAX(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3291,7 +3341,7 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short max(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3659,7 +3709,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ANDReduce(short[] a, int idx) { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3668,7 +3718,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ANDReduceAll(short[] a) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3686,7 +3736,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3699,20 +3749,20 @@ public class ShortVector256Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = AND_IDENTITY; - assertEquals((short) (id & id), id, + assertEquals((short) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id & x), x); - assertEquals((short) (x & id), x); + assertEquals((short) (scalar_and(id, x)), x); + assertEquals((short) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id & x), x, + assertEquals((short) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x & id), x, + assertEquals((short) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3721,7 +3771,7 @@ public class ShortVector256Tests extends AbstractVectorTest { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3730,7 +3780,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ANDReduceAllMasked(short[] a, boolean[] mask) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3750,7 +3800,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3761,7 +3811,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ORReduce(short[] a, int idx) { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3770,7 +3820,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ORReduceAll(short[] a) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3788,7 +3838,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3801,20 +3851,20 @@ public class ShortVector256Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = OR_IDENTITY; - assertEquals((short) (id | id), id, + assertEquals((short) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id | x), x); - assertEquals((short) (x | id), x); + assertEquals((short) (scalar_or(id, x)), x); + assertEquals((short) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id | x), x, + assertEquals((short) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x | id), x, + assertEquals((short) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3823,7 +3873,7 @@ public class ShortVector256Tests extends AbstractVectorTest { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3832,7 +3882,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ORReduceAllMasked(short[] a, boolean[] mask) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3852,7 +3902,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3863,7 +3913,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short XORReduce(short[] a, int idx) { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3872,7 +3922,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short XORReduceAll(short[] a) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3890,7 +3940,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3903,20 +3953,20 @@ public class ShortVector256Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = XOR_IDENTITY; - assertEquals((short) (id ^ id), id, + assertEquals((short) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id ^ x), x); - assertEquals((short) (x ^ id), x); + assertEquals((short) (scalar_xor(id, x)), x); + assertEquals((short) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id ^ x), x, + assertEquals((short) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x ^ id), x, + assertEquals((short) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3925,7 +3975,7 @@ public class ShortVector256Tests extends AbstractVectorTest { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3934,7 +3984,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short XORReduceAllMasked(short[] a, boolean[] mask) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3954,7 +4004,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3965,7 +4015,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ADDReduce(short[] a, int idx) { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3974,7 +4024,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ADDReduceAll(short[] a) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -3992,7 +4042,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4005,20 +4055,20 @@ public class ShortVector256Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = ADD_IDENTITY; - assertEquals((short) (id + id), id, + assertEquals((short) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id + x), x); - assertEquals((short) (x + id), x); + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id + x), x, + assertEquals((short) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x + id), x, + assertEquals((short) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4027,7 +4077,7 @@ public class ShortVector256Tests extends AbstractVectorTest { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4036,7 +4086,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short ADDReduceAllMasked(short[] a, boolean[] mask) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4056,7 +4106,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4067,7 +4117,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MULReduce(short[] a, int idx) { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4076,7 +4126,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MULReduceAll(short[] a) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4094,7 +4144,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4107,20 +4157,20 @@ public class ShortVector256Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MUL_IDENTITY; - assertEquals((short) (id * id), id, + assertEquals((short) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id * x), x); - assertEquals((short) (x * id), x); + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id * x), x, + assertEquals((short) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x * id), x, + assertEquals((short) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4129,7 +4179,7 @@ public class ShortVector256Tests extends AbstractVectorTest { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4138,7 +4188,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MULReduceAllMasked(short[] a, boolean[] mask) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4158,7 +4208,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4169,7 +4219,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4178,7 +4228,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4196,7 +4246,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4209,20 +4259,20 @@ public class ShortVector256Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MIN_IDENTITY; - assertEquals((short) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.min(id, x), x); - assertEquals((short) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4231,7 +4281,7 @@ public class ShortVector256Tests extends AbstractVectorTest { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4240,7 +4290,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4260,7 +4310,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4271,7 +4321,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4280,7 +4330,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4298,7 +4348,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4311,20 +4361,20 @@ public class ShortVector256Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MAX_IDENTITY; - assertEquals((short) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.max(id, x), x); - assertEquals((short) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4333,7 +4383,7 @@ public class ShortVector256Tests extends AbstractVectorTest { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4342,7 +4392,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4362,7 +4412,7 @@ public class ShortVector256Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5395,7 +5445,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5415,7 +5465,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5431,7 +5481,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (short)((long)b[i]))); } } } @@ -5451,7 +5501,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (short)((long)b[i])))); } } } @@ -5467,7 +5517,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5487,7 +5537,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5503,7 +5553,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (short)((long)b[i]))); } } } @@ -5523,7 +5573,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (short)((long)b[i])))); } } } @@ -6235,11 +6285,11 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short NEG(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } static short neg(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6291,11 +6341,11 @@ public class ShortVector256Tests extends AbstractVectorTest { } static short ABS(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } static short abs(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6786,7 +6836,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6802,7 +6852,7 @@ public class ShortVector256Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6871,7 +6921,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static long ADDReduceLong(short[] a, int idx) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6880,7 +6930,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static long ADDReduceAllLong(short[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); } return res; @@ -6898,8 +6948,8 @@ public class ShortVector256Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6909,8 +6959,9 @@ public class ShortVector256Tests extends AbstractVectorTest { static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6919,7 +6970,7 @@ public class ShortVector256Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6939,8 +6990,8 @@ public class ShortVector256Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ShortVector512Tests.java b/test/jdk/jdk/incubator/vector/ShortVector512Tests.java index 69dc6d8019f..ae5804c3688 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector512Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector512Tests.java @@ -1565,6 +1565,59 @@ public class ShortVector512Tests extends AbstractVectorTest { return a >= b; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + + static short scalar_or(short a, short b) { + return (short)(a | b); + } + + static short scalar_and(short a, short b) { + return (short)(a & b); + } + + static short scalar_xor(short a, short b) { + return (short)(a ^ b); + } + + static short scalar_add(short a, short b) { + return (short)(a + b); + } + + static short scalar_sub(short a, short b) { + return (short)(a - b); + } + + static short scalar_mul(short a, short b) { + return (short)(a * b); + } + + static short scalar_min(short a, short b) { + return (short)(Math.min(a, b)); + } + + static short scalar_max(short a, short b) { + return (short)(Math.max(a, b)); + } + + static short scalar_div(short a, short b) { + return (short)(a / b); + } + + static short scalar_fma(short a, short b, short c) { + return (short)(Math.fma(a, b, c)); + } + + static short scalar_abs(short a) { + return (short)(Math.abs(a)); + } + + static short scalar_neg(short a) { + return ((short)-a); + } + + static boolean ult(short a, short b) { return Short.compareUnsigned(a, b) < 0; } @@ -1581,9 +1634,6 @@ public class ShortVector512Tests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } - static short firstNonZero(short a, short b) { - return Short.compare(a, (short) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1692,7 +1742,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short ADD(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1713,7 +1763,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short add(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1770,7 +1820,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short SUB(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1791,7 +1841,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short sub(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1848,7 +1898,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short MUL(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1869,7 +1919,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short mul(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -2016,7 +2066,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short FIRST_NONZERO(short a, short b) { - return (short)((a)!=0?a:b); + return (short)(firstNonZero(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3230,7 +3280,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short MIN(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3251,7 +3301,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short min(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3270,7 +3320,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short MAX(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3291,7 +3341,7 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short max(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3659,7 +3709,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ANDReduce(short[] a, int idx) { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3668,7 +3718,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ANDReduceAll(short[] a) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3686,7 +3736,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3699,20 +3749,20 @@ public class ShortVector512Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = AND_IDENTITY; - assertEquals((short) (id & id), id, + assertEquals((short) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id & x), x); - assertEquals((short) (x & id), x); + assertEquals((short) (scalar_and(id, x)), x); + assertEquals((short) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id & x), x, + assertEquals((short) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x & id), x, + assertEquals((short) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3721,7 +3771,7 @@ public class ShortVector512Tests extends AbstractVectorTest { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3730,7 +3780,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ANDReduceAllMasked(short[] a, boolean[] mask) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3750,7 +3800,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3761,7 +3811,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ORReduce(short[] a, int idx) { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3770,7 +3820,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ORReduceAll(short[] a) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3788,7 +3838,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3801,20 +3851,20 @@ public class ShortVector512Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = OR_IDENTITY; - assertEquals((short) (id | id), id, + assertEquals((short) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id | x), x); - assertEquals((short) (x | id), x); + assertEquals((short) (scalar_or(id, x)), x); + assertEquals((short) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id | x), x, + assertEquals((short) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x | id), x, + assertEquals((short) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3823,7 +3873,7 @@ public class ShortVector512Tests extends AbstractVectorTest { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3832,7 +3882,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ORReduceAllMasked(short[] a, boolean[] mask) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3852,7 +3902,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3863,7 +3913,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short XORReduce(short[] a, int idx) { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3872,7 +3922,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short XORReduceAll(short[] a) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3890,7 +3940,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3903,20 +3953,20 @@ public class ShortVector512Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = XOR_IDENTITY; - assertEquals((short) (id ^ id), id, + assertEquals((short) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id ^ x), x); - assertEquals((short) (x ^ id), x); + assertEquals((short) (scalar_xor(id, x)), x); + assertEquals((short) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id ^ x), x, + assertEquals((short) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x ^ id), x, + assertEquals((short) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3925,7 +3975,7 @@ public class ShortVector512Tests extends AbstractVectorTest { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3934,7 +3984,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short XORReduceAllMasked(short[] a, boolean[] mask) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3954,7 +4004,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3965,7 +4015,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ADDReduce(short[] a, int idx) { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3974,7 +4024,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ADDReduceAll(short[] a) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -3992,7 +4042,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4005,20 +4055,20 @@ public class ShortVector512Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = ADD_IDENTITY; - assertEquals((short) (id + id), id, + assertEquals((short) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id + x), x); - assertEquals((short) (x + id), x); + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id + x), x, + assertEquals((short) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x + id), x, + assertEquals((short) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4027,7 +4077,7 @@ public class ShortVector512Tests extends AbstractVectorTest { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4036,7 +4086,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short ADDReduceAllMasked(short[] a, boolean[] mask) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4056,7 +4106,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4067,7 +4117,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MULReduce(short[] a, int idx) { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4076,7 +4126,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MULReduceAll(short[] a) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4094,7 +4144,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4107,20 +4157,20 @@ public class ShortVector512Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MUL_IDENTITY; - assertEquals((short) (id * id), id, + assertEquals((short) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id * x), x); - assertEquals((short) (x * id), x); + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id * x), x, + assertEquals((short) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x * id), x, + assertEquals((short) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4129,7 +4179,7 @@ public class ShortVector512Tests extends AbstractVectorTest { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4138,7 +4188,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MULReduceAllMasked(short[] a, boolean[] mask) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4158,7 +4208,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4169,7 +4219,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4178,7 +4228,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4196,7 +4246,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4209,20 +4259,20 @@ public class ShortVector512Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MIN_IDENTITY; - assertEquals((short) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.min(id, x), x); - assertEquals((short) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4231,7 +4281,7 @@ public class ShortVector512Tests extends AbstractVectorTest { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4240,7 +4290,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4260,7 +4310,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4271,7 +4321,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4280,7 +4330,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4298,7 +4348,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4311,20 +4361,20 @@ public class ShortVector512Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MAX_IDENTITY; - assertEquals((short) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.max(id, x), x); - assertEquals((short) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4333,7 +4383,7 @@ public class ShortVector512Tests extends AbstractVectorTest { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4342,7 +4392,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4362,7 +4412,7 @@ public class ShortVector512Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5395,7 +5445,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5415,7 +5465,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5431,7 +5481,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (short)((long)b[i]))); } } } @@ -5451,7 +5501,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (short)((long)b[i])))); } } } @@ -5467,7 +5517,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5487,7 +5537,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5503,7 +5553,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (short)((long)b[i]))); } } } @@ -5523,7 +5573,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (short)((long)b[i])))); } } } @@ -6235,11 +6285,11 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short NEG(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } static short neg(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6291,11 +6341,11 @@ public class ShortVector512Tests extends AbstractVectorTest { } static short ABS(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } static short abs(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6786,7 +6836,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6802,7 +6852,7 @@ public class ShortVector512Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6871,7 +6921,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static long ADDReduceLong(short[] a, int idx) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6880,7 +6930,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static long ADDReduceAllLong(short[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); } return res; @@ -6898,8 +6948,8 @@ public class ShortVector512Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6909,8 +6959,9 @@ public class ShortVector512Tests extends AbstractVectorTest { static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6919,7 +6970,7 @@ public class ShortVector512Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6939,8 +6990,8 @@ public class ShortVector512Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ShortVector64Tests.java b/test/jdk/jdk/incubator/vector/ShortVector64Tests.java index dd9f7125853..5f84682f02f 100644 --- a/test/jdk/jdk/incubator/vector/ShortVector64Tests.java +++ b/test/jdk/jdk/incubator/vector/ShortVector64Tests.java @@ -1565,6 +1565,59 @@ public class ShortVector64Tests extends AbstractVectorTest { return a >= b; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + + static short scalar_or(short a, short b) { + return (short)(a | b); + } + + static short scalar_and(short a, short b) { + return (short)(a & b); + } + + static short scalar_xor(short a, short b) { + return (short)(a ^ b); + } + + static short scalar_add(short a, short b) { + return (short)(a + b); + } + + static short scalar_sub(short a, short b) { + return (short)(a - b); + } + + static short scalar_mul(short a, short b) { + return (short)(a * b); + } + + static short scalar_min(short a, short b) { + return (short)(Math.min(a, b)); + } + + static short scalar_max(short a, short b) { + return (short)(Math.max(a, b)); + } + + static short scalar_div(short a, short b) { + return (short)(a / b); + } + + static short scalar_fma(short a, short b, short c) { + return (short)(Math.fma(a, b, c)); + } + + static short scalar_abs(short a) { + return (short)(Math.abs(a)); + } + + static short scalar_neg(short a) { + return ((short)-a); + } + + static boolean ult(short a, short b) { return Short.compareUnsigned(a, b) < 0; } @@ -1581,9 +1634,6 @@ public class ShortVector64Tests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } - static short firstNonZero(short a, short b) { - return Short.compare(a, (short) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1692,7 +1742,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short ADD(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1713,7 +1763,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short add(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1770,7 +1820,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short SUB(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1791,7 +1841,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short sub(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1848,7 +1898,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short MUL(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1869,7 +1919,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short mul(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -2016,7 +2066,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short FIRST_NONZERO(short a, short b) { - return (short)((a)!=0?a:b); + return (short)(firstNonZero(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3230,7 +3280,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short MIN(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3251,7 +3301,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short min(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3270,7 +3320,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short MAX(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3291,7 +3341,7 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short max(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3659,7 +3709,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ANDReduce(short[] a, int idx) { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3668,7 +3718,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ANDReduceAll(short[] a) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3686,7 +3736,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3699,20 +3749,20 @@ public class ShortVector64Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = AND_IDENTITY; - assertEquals((short) (id & id), id, + assertEquals((short) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id & x), x); - assertEquals((short) (x & id), x); + assertEquals((short) (scalar_and(id, x)), x); + assertEquals((short) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id & x), x, + assertEquals((short) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x & id), x, + assertEquals((short) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3721,7 +3771,7 @@ public class ShortVector64Tests extends AbstractVectorTest { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3730,7 +3780,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ANDReduceAllMasked(short[] a, boolean[] mask) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3750,7 +3800,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3761,7 +3811,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ORReduce(short[] a, int idx) { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3770,7 +3820,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ORReduceAll(short[] a) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3788,7 +3838,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3801,20 +3851,20 @@ public class ShortVector64Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = OR_IDENTITY; - assertEquals((short) (id | id), id, + assertEquals((short) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id | x), x); - assertEquals((short) (x | id), x); + assertEquals((short) (scalar_or(id, x)), x); + assertEquals((short) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id | x), x, + assertEquals((short) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x | id), x, + assertEquals((short) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3823,7 +3873,7 @@ public class ShortVector64Tests extends AbstractVectorTest { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3832,7 +3882,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ORReduceAllMasked(short[] a, boolean[] mask) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3852,7 +3902,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3863,7 +3913,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short XORReduce(short[] a, int idx) { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3872,7 +3922,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short XORReduceAll(short[] a) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3890,7 +3940,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3903,20 +3953,20 @@ public class ShortVector64Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = XOR_IDENTITY; - assertEquals((short) (id ^ id), id, + assertEquals((short) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id ^ x), x); - assertEquals((short) (x ^ id), x); + assertEquals((short) (scalar_xor(id, x)), x); + assertEquals((short) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id ^ x), x, + assertEquals((short) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x ^ id), x, + assertEquals((short) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3925,7 +3975,7 @@ public class ShortVector64Tests extends AbstractVectorTest { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3934,7 +3984,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short XORReduceAllMasked(short[] a, boolean[] mask) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3954,7 +4004,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3965,7 +4015,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ADDReduce(short[] a, int idx) { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3974,7 +4024,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ADDReduceAll(short[] a) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -3992,7 +4042,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4005,20 +4055,20 @@ public class ShortVector64Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = ADD_IDENTITY; - assertEquals((short) (id + id), id, + assertEquals((short) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id + x), x); - assertEquals((short) (x + id), x); + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id + x), x, + assertEquals((short) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x + id), x, + assertEquals((short) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4027,7 +4077,7 @@ public class ShortVector64Tests extends AbstractVectorTest { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4036,7 +4086,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short ADDReduceAllMasked(short[] a, boolean[] mask) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4056,7 +4106,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4067,7 +4117,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MULReduce(short[] a, int idx) { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4076,7 +4126,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MULReduceAll(short[] a) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4094,7 +4144,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4107,20 +4157,20 @@ public class ShortVector64Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MUL_IDENTITY; - assertEquals((short) (id * id), id, + assertEquals((short) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id * x), x); - assertEquals((short) (x * id), x); + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id * x), x, + assertEquals((short) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x * id), x, + assertEquals((short) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4129,7 +4179,7 @@ public class ShortVector64Tests extends AbstractVectorTest { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4138,7 +4188,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MULReduceAllMasked(short[] a, boolean[] mask) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4158,7 +4208,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4169,7 +4219,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4178,7 +4228,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4196,7 +4246,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4209,20 +4259,20 @@ public class ShortVector64Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MIN_IDENTITY; - assertEquals((short) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.min(id, x), x); - assertEquals((short) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4231,7 +4281,7 @@ public class ShortVector64Tests extends AbstractVectorTest { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4240,7 +4290,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4260,7 +4310,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4271,7 +4321,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4280,7 +4330,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4298,7 +4348,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4311,20 +4361,20 @@ public class ShortVector64Tests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MAX_IDENTITY; - assertEquals((short) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.max(id, x), x); - assertEquals((short) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4333,7 +4383,7 @@ public class ShortVector64Tests extends AbstractVectorTest { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4342,7 +4392,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4362,7 +4412,7 @@ public class ShortVector64Tests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5395,7 +5445,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5415,7 +5465,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5431,7 +5481,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (short)((long)b[i]))); } } } @@ -5451,7 +5501,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (short)((long)b[i])))); } } } @@ -5467,7 +5517,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5487,7 +5537,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5503,7 +5553,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (short)((long)b[i]))); } } } @@ -5523,7 +5573,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (short)((long)b[i])))); } } } @@ -6235,11 +6285,11 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short NEG(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } static short neg(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6291,11 +6341,11 @@ public class ShortVector64Tests extends AbstractVectorTest { } static short ABS(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } static short abs(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6786,7 +6836,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6802,7 +6852,7 @@ public class ShortVector64Tests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6871,7 +6921,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static long ADDReduceLong(short[] a, int idx) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6880,7 +6930,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static long ADDReduceAllLong(short[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); } return res; @@ -6898,8 +6948,8 @@ public class ShortVector64Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6909,8 +6959,9 @@ public class ShortVector64Tests extends AbstractVectorTest { static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6919,7 +6970,7 @@ public class ShortVector64Tests extends AbstractVectorTest { static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6939,8 +6990,8 @@ public class ShortVector64Tests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java b/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java index 65234fb3173..5451ad6c50e 100644 --- a/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java +++ b/test/jdk/jdk/incubator/vector/ShortVectorMaxTests.java @@ -1571,6 +1571,59 @@ public class ShortVectorMaxTests extends AbstractVectorTest { return a >= b; } + static short firstNonZero(short a, short b) { + return Short.compare(a, (short) 0) != 0 ? a : b; + } + + static short scalar_or(short a, short b) { + return (short)(a | b); + } + + static short scalar_and(short a, short b) { + return (short)(a & b); + } + + static short scalar_xor(short a, short b) { + return (short)(a ^ b); + } + + static short scalar_add(short a, short b) { + return (short)(a + b); + } + + static short scalar_sub(short a, short b) { + return (short)(a - b); + } + + static short scalar_mul(short a, short b) { + return (short)(a * b); + } + + static short scalar_min(short a, short b) { + return (short)(Math.min(a, b)); + } + + static short scalar_max(short a, short b) { + return (short)(Math.max(a, b)); + } + + static short scalar_div(short a, short b) { + return (short)(a / b); + } + + static short scalar_fma(short a, short b, short c) { + return (short)(Math.fma(a, b, c)); + } + + static short scalar_abs(short a) { + return (short)(Math.abs(a)); + } + + static short scalar_neg(short a) { + return ((short)-a); + } + + static boolean ult(short a, short b) { return Short.compareUnsigned(a, b) < 0; } @@ -1587,9 +1640,6 @@ public class ShortVectorMaxTests extends AbstractVectorTest { return Short.compareUnsigned(a, b) >= 0; } - static short firstNonZero(short a, short b) { - return Short.compare(a, (short) 0) != 0 ? a : b; - } @Test static void smokeTest1() { @@ -1698,7 +1748,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short ADD(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1719,7 +1769,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short add(short a, short b) { - return (short)(a + b); + return (short)(scalar_add(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1776,7 +1826,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short SUB(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1797,7 +1847,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short sub(short a, short b) { - return (short)(a - b); + return (short)(scalar_sub(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1854,7 +1904,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short MUL(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -1875,7 +1925,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short mul(short a, short b) { - return (short)(a * b); + return (short)(scalar_mul(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -2022,7 +2072,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short FIRST_NONZERO(short a, short b) { - return (short)((a)!=0?a:b); + return (short)(firstNonZero(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3236,7 +3286,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short MIN(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3257,7 +3307,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short min(short a, short b) { - return (short)(Math.min(a, b)); + return (short)(scalar_min(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3276,7 +3326,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short MAX(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3297,7 +3347,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short max(short a, short b) { - return (short)(Math.max(a, b)); + return (short)(scalar_max(a, b)); } @Test(dataProvider = "shortBinaryOpProvider") @@ -3665,7 +3715,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ANDReduce(short[] a, int idx) { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3674,7 +3724,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ANDReduceAll(short[] a) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduce(a, i); + res = scalar_and(res, ANDReduce(a, i)); } return res; @@ -3692,7 +3742,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3705,20 +3755,20 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = AND_IDENTITY; - assertEquals((short) (id & id), id, + assertEquals((short) (scalar_and(id, id)), id, "AND(AND_IDENTITY, AND_IDENTITY) != AND_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id & x), x); - assertEquals((short) (x & id), x); + assertEquals((short) (scalar_and(id, x)), x); + assertEquals((short) (scalar_and(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id & x), x, + assertEquals((short) (scalar_and(id, x)), x, "AND(AND_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x & id), x, + assertEquals((short) (scalar_and(x, id)), x, "AND(" + x + ", AND_IDENTITY) != " + x); } } @@ -3727,7 +3777,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short res = AND_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res &= a[i]; + res = scalar_and(res, a[i]); } return res; @@ -3736,7 +3786,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ANDReduceAllMasked(short[] a, boolean[] mask) { short res = AND_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res &= ANDReduceMasked(a, i, mask); + res = scalar_and(res, ANDReduceMasked(a, i, mask)); } return res; @@ -3756,7 +3806,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.AND, vmask); r[i] = v; - ra &= v; + ra = scalar_and(ra, v); } } @@ -3767,7 +3817,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ORReduce(short[] a, int idx) { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3776,7 +3826,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ORReduceAll(short[] a) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduce(a, i); + res = scalar_or(res, ORReduce(a, i)); } return res; @@ -3794,7 +3844,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3807,20 +3857,20 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = OR_IDENTITY; - assertEquals((short) (id | id), id, + assertEquals((short) (scalar_or(id, id)), id, "OR(OR_IDENTITY, OR_IDENTITY) != OR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id | x), x); - assertEquals((short) (x | id), x); + assertEquals((short) (scalar_or(id, x)), x); + assertEquals((short) (scalar_or(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id | x), x, + assertEquals((short) (scalar_or(id, x)), x, "OR(OR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x | id), x, + assertEquals((short) (scalar_or(x, id)), x, "OR(" + x + ", OR_IDENTITY) != " + x); } } @@ -3829,7 +3879,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short res = OR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res |= a[i]; + res = scalar_or(res, a[i]); } return res; @@ -3838,7 +3888,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ORReduceAllMasked(short[] a, boolean[] mask) { short res = OR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res |= ORReduceMasked(a, i, mask); + res = scalar_or(res, ORReduceMasked(a, i, mask)); } return res; @@ -3858,7 +3908,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.OR, vmask); r[i] = v; - ra |= v; + ra = scalar_or(ra, v); } } @@ -3869,7 +3919,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short XORReduce(short[] a, int idx) { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3878,7 +3928,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short XORReduceAll(short[] a) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduce(a, i); + res = scalar_xor(res, XORReduce(a, i)); } return res; @@ -3896,7 +3946,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3909,20 +3959,20 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = XOR_IDENTITY; - assertEquals((short) (id ^ id), id, + assertEquals((short) (scalar_xor(id, id)), id, "XOR(XOR_IDENTITY, XOR_IDENTITY) != XOR_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id ^ x), x); - assertEquals((short) (x ^ id), x); + assertEquals((short) (scalar_xor(id, x)), x); + assertEquals((short) (scalar_xor(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id ^ x), x, + assertEquals((short) (scalar_xor(id, x)), x, "XOR(XOR_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x ^ id), x, + assertEquals((short) (scalar_xor(x, id)), x, "XOR(" + x + ", XOR_IDENTITY) != " + x); } } @@ -3931,7 +3981,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short res = XOR_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res ^= a[i]; + res = scalar_xor(res, a[i]); } return res; @@ -3940,7 +3990,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short XORReduceAllMasked(short[] a, boolean[] mask) { short res = XOR_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res ^= XORReduceMasked(a, i, mask); + res = scalar_xor(res, XORReduceMasked(a, i, mask)); } return res; @@ -3960,7 +4010,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.XOR, vmask); r[i] = v; - ra ^= v; + ra = scalar_xor(ra, v); } } @@ -3971,7 +4021,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ADDReduce(short[] a, int idx) { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -3980,7 +4030,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ADDReduceAll(short[] a) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduce(a, i); + res = scalar_add(res, ADDReduce(a, i)); } return res; @@ -3998,7 +4048,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4011,20 +4061,20 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = ADD_IDENTITY; - assertEquals((short) (id + id), id, + assertEquals((short) (scalar_add(id, id)), id, "ADD(ADD_IDENTITY, ADD_IDENTITY) != ADD_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id + x), x); - assertEquals((short) (x + id), x); + assertEquals((short) (scalar_add(id, x)), x); + assertEquals((short) (scalar_add(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id + x), x, + assertEquals((short) (scalar_add(id, x)), x, "ADD(ADD_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x + id), x, + assertEquals((short) (scalar_add(x, id)), x, "ADD(" + x + ", ADD_IDENTITY) != " + x); } } @@ -4033,7 +4083,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short res = ADD_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res += a[i]; + res = scalar_add(res, a[i]); } return res; @@ -4042,7 +4092,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short ADDReduceAllMasked(short[] a, boolean[] mask) { short res = ADD_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceMasked(a, i, mask); + res = scalar_add(res, ADDReduceMasked(a, i, mask)); } return res; @@ -4062,7 +4112,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.ADD, vmask); r[i] = v; - ra += v; + ra = scalar_add(ra, v); } } @@ -4073,7 +4123,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MULReduce(short[] a, int idx) { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4082,7 +4132,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MULReduceAll(short[] a) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduce(a, i); + res = scalar_mul(res, MULReduce(a, i)); } return res; @@ -4100,7 +4150,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4113,20 +4163,20 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MUL_IDENTITY; - assertEquals((short) (id * id), id, + assertEquals((short) (scalar_mul(id, id)), id, "MUL(MUL_IDENTITY, MUL_IDENTITY) != MUL_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) (id * x), x); - assertEquals((short) (x * id), x); + assertEquals((short) (scalar_mul(id, x)), x); + assertEquals((short) (scalar_mul(x, id)), x); } } catch (AssertionError e) { - assertEquals((short) (id * x), x, + assertEquals((short) (scalar_mul(id, x)), x, "MUL(MUL_IDENTITY, " + x + ") != " + x); - assertEquals((short) (x * id), x, + assertEquals((short) (scalar_mul(x, id)), x, "MUL(" + x + ", MUL_IDENTITY) != " + x); } } @@ -4135,7 +4185,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short res = MUL_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res *= a[i]; + res = scalar_mul(res, a[i]); } return res; @@ -4144,7 +4194,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MULReduceAllMasked(short[] a, boolean[] mask) { short res = MUL_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res *= MULReduceMasked(a, i, mask); + res = scalar_mul(res, MULReduceMasked(a, i, mask)); } return res; @@ -4164,7 +4214,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MUL, vmask); r[i] = v; - ra *= v; + ra = scalar_mul(ra, v); } } @@ -4175,7 +4225,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MINReduce(short[] a, int idx) { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4184,7 +4234,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MINReduceAll(short[] a) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduce(a, i)); + res = scalar_min(res, MINReduce(a, i)); } return res; @@ -4202,7 +4252,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4215,20 +4265,20 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MIN_IDENTITY; - assertEquals((short) Math.min(id, id), id, + assertEquals(scalar_min(id, id), id, "MIN(MIN_IDENTITY, MIN_IDENTITY) != MIN_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.min(id, x), x); - assertEquals((short) Math.min(x, id), x); + assertEquals(scalar_min(id, x), x); + assertEquals(scalar_min(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.min(id, x), x, + assertEquals(scalar_min(id, x), x, "MIN(MIN_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.min(x, id), x, + assertEquals(scalar_min(x, id), x, "MIN(" + x + ", MIN_IDENTITY) != " + x); } } @@ -4237,7 +4287,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short res = MIN_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.min(res, a[i]); + res = scalar_min(res, a[i]); } return res; @@ -4246,7 +4296,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MINReduceAllMasked(short[] a, boolean[] mask) { short res = MIN_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.min(res, MINReduceMasked(a, i, mask)); + res = scalar_min(res, MINReduceMasked(a, i, mask)); } return res; @@ -4266,7 +4316,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MIN, vmask); r[i] = v; - ra = (short) Math.min(ra, v); + ra = scalar_min(ra, v); } } @@ -4277,7 +4327,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MAXReduce(short[] a, int idx) { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4286,7 +4336,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MAXReduceAll(short[] a) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduce(a, i)); + res = scalar_max(res, MAXReduce(a, i)); } return res; @@ -4304,7 +4354,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -4317,20 +4367,20 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short[] a = fa.apply(SPECIES.length()); short id = MAX_IDENTITY; - assertEquals((short) Math.max(id, id), id, + assertEquals(scalar_max(id, id), id, "MAX(MAX_IDENTITY, MAX_IDENTITY) != MAX_IDENTITY"); short x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals((short) Math.max(id, x), x); - assertEquals((short) Math.max(x, id), x); + assertEquals(scalar_max(id, x), x); + assertEquals(scalar_max(x, id), x); } } catch (AssertionError e) { - assertEquals((short) Math.max(id, x), x, + assertEquals(scalar_max(id, x), x, "MAX(MAX_IDENTITY, " + x + ") != " + x); - assertEquals((short) Math.max(x, id), x, + assertEquals(scalar_max(x, id), x, "MAX(" + x + ", MAX_IDENTITY) != " + x); } } @@ -4339,7 +4389,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { short res = MAX_IDENTITY; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res = (short) Math.max(res, a[i]); + res = scalar_max(res, a[i]); } return res; @@ -4348,7 +4398,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static short MAXReduceAllMasked(short[] a, boolean[] mask) { short res = MAX_IDENTITY; for (int i = 0; i < a.length; i += SPECIES.length()) { - res = (short) Math.max(res, MAXReduceMasked(a, i, mask)); + res = scalar_max(res, MAXReduceMasked(a, i, mask)); } return res; @@ -4368,7 +4418,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { ShortVector av = ShortVector.fromArray(SPECIES, a, i); short v = av.reduceLanes(VectorOperators.MAX, vmask); r[i] = v; - ra = (short) Math.max(ra, v); + ra = scalar_max(ra, v); } } @@ -5401,7 +5451,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -5421,7 +5471,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], b[i]))); } } } @@ -5437,7 +5487,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), lt(a[i + j], (short)((long)b[i]))); } } } @@ -5457,7 +5507,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] < (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (lt(a[i + j], (short)((long)b[i])))); } } } @@ -5473,7 +5523,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -5493,7 +5543,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], b[i]))); } } } @@ -5509,7 +5559,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == (short)((long)b[i])); + assertEquals(mv.laneIsSet(j), eq(a[i + j], (short)((long)b[i]))); } } } @@ -5529,7 +5579,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] == (short)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && (eq(a[i + j], (short)((long)b[i])))); } } } @@ -6241,11 +6291,11 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short NEG(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } static short neg(short a) { - return (short)(-((short)a)); + return (short)(scalar_neg((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6297,11 +6347,11 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } static short ABS(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } static short abs(short a) { - return (short)(Math.abs((short)a)); + return (short)(scalar_abs((short)a)); } @Test(dataProvider = "shortUnaryOpProvider") @@ -6792,7 +6842,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -6808,7 +6858,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -6877,7 +6927,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static long ADDReduceLong(short[] a, int idx) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -6886,7 +6936,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static long ADDReduceAllLong(short[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add((short)res, (short)ADDReduceLong(a, i)); } return res; @@ -6904,8 +6954,8 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -6915,8 +6965,9 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static long ADDReduceLongMasked(short[] a, int idx, boolean[] mask) { short res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -6925,7 +6976,7 @@ public class ShortVectorMaxTests extends AbstractVectorTest { static long ADDReduceAllLongMasked(short[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add((short)res, (short)ADDReduceLongMasked(a, i, mask)); } return res; @@ -6945,8 +6996,8 @@ public class ShortVectorMaxTests extends AbstractVectorTest { } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add((short)ra, (short)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/gen-template.sh b/test/jdk/jdk/incubator/vector/gen-template.sh index d2528b13b78..4e961e2f2b0 100644 --- a/test/jdk/jdk/incubator/vector/gen-template.sh +++ b/test/jdk/jdk/incubator/vector/gen-template.sh @@ -383,6 +383,7 @@ function gen_bool_reduction_op { gen_op_tmpl $bool_reduction_scalar "$@" gen_op_tmpl $bool_reduction_template "$@" } + function gen_saturating_reduction_op { echo "Generating saturating reduction op $1 ($2)..." gen_op_tmpl $reduction_scalar_func "$@" @@ -434,13 +435,13 @@ fi # ALU binary ops. # Here "ADD+add+withMask" says VectorOperator name is "ADD", and we have a dedicate method too named 'add', and add() is also available with mask variant. -gen_binary_alu_op "ADD+add+withMask" "a + b" -gen_binary_alu_op "SUB+sub+withMask" "a - b" -gen_binary_alu_op "MUL+mul+withMask" "a \* b" -gen_binary_alu_op "DIV+div+withMask" "a \/ b" "FP" +gen_binary_alu_op "ADD+add+withMask" "scalar_add(a, b)" +gen_binary_alu_op "SUB+sub+withMask" "scalar_sub(a, b)" +gen_binary_alu_op "MUL+mul+withMask" "scalar_mul(a, b)" +gen_binary_alu_op "DIV+div+withMask" "scalar_div(a, b)" "FP" gen_op_tmpl "Binary-op_bitwise-div" "DIV+div+withMask" "a \/ b" "BITWISE" gen_op_tmpl "Binary-Masked-op_bitwise-div" "DIV+div+withMask" "a \/ b" "BITWISE" -gen_binary_alu_op "FIRST_NONZERO" "{#if[FP]?Double.doubleToLongBits}(a)!=0?a:b" +gen_binary_alu_op "FIRST_NONZERO" "firstNonZero(a, b)" gen_binary_alu_op "AND+and" "a \& b" "BITWISE" gen_binary_alu_op "AND_NOT" "a \& ~b" "BITWISE" gen_binary_alu_op "OR+or" "a | b" "BITWISE" @@ -449,16 +450,16 @@ gen_binary_alu_op "XOR" "a ^ b" "BITWISE" gen_binary_alu_op "COMPRESS_BITS" "\$Boxtype\$.compress(a, b)" "intOrLong" gen_binary_alu_op "EXPAND_BITS" "\$Boxtype\$.expand(a, b)" "intOrLong" # Generate the broadcast versions -gen_binary_alu_bcst_op "add+withMask" "a + b" -gen_binary_alu_bcst_op "sub+withMask" "a - b" -gen_binary_alu_bcst_op "mul+withMask" "a \* b" -gen_binary_alu_bcst_op "div+withMask" "a \/ b" "FP" +gen_binary_alu_bcst_op "add+withMask" "scalar_add(a, b)" +gen_binary_alu_bcst_op "sub+withMask" "scalar_sub(a, b)" +gen_binary_alu_bcst_op "mul+withMask" "scalar_mul(a, b)" +gen_binary_alu_bcst_op "div+withMask" "scalar_div(a, b)" "FP" gen_op_tmpl "Binary-Broadcast-op_bitwise-div" "div+withMask" "a \/ b" "BITWISE" gen_op_tmpl "Binary-Broadcast-Masked-op_bitwise-div" "div+withMask" "a \/ b" "BITWISE" gen_binary_alu_bcst_op "OR+or" "a | b" "BITWISE" gen_binary_alu_bcst_op "AND+and" "a \& b" "BITWISE" gen_binary_alu_bcst_long_op "OR" "a | b" "BITWISE" -gen_binary_alu_bcst_long_op "ADD" "a + b" +gen_binary_alu_bcst_long_op "ADD" "scalar_add(a, b)" # Shifts gen_binary_alu_op "LSHL" "(a << b)" "intOrLong" @@ -494,30 +495,30 @@ gen_shift_cst_op "ROR" "ROR_scalar(a, CONST_SHIFT)" "BITWISE" gen_shift_cst_op "ROL" "ROL_scalar(a, CONST_SHIFT)" "BITWISE" # Binary operation with one memory operand -gen_binary_alu_mem_op "MIN+min+withMask", "Math.min(a, b)" -gen_binary_alu_mem_op "MAX+max+withMask", "Math.max(a, b)" +gen_binary_alu_mem_op "MIN+min+withMask", "scalar_min(a, b)" +gen_binary_alu_mem_op "MAX+max+withMask", "scalar_max(a, b)" # Masked reductions. -gen_binary_op_no_masked "MIN+min" "Math.min(a, b)" -gen_binary_op_no_masked "MAX+max" "Math.max(a, b)" +gen_binary_op_no_masked "MIN+min" "scalar_min(a, b)" +gen_binary_op_no_masked "MAX+max" "scalar_max(a, b)" gen_binary_op "UMIN" "VectorMath.minUnsigned(a, b)" "BITWISE" gen_binary_op "UMAX" "VectorMath.maxUnsigned(a, b)" "BITWISE" gen_saturating_binary_op "SADD" "VectorMath.addSaturating(a, b)" "BITWISE" gen_saturating_binary_op "SSUB" "VectorMath.subSaturating(a, b)" "BITWISE" gen_saturating_binary_op "SUADD" "VectorMath.addSaturatingUnsigned(a, b)" "BITWISE" gen_saturating_binary_op "SUSUB" "VectorMath.subSaturatingUnsigned(a, b)" "BITWISE" -gen_binary_bcst_op_no_masked "MIN+min" "Math.min(a, b)" -gen_binary_bcst_op_no_masked "MAX+max" "Math.max(a, b)" +gen_binary_bcst_op_no_masked "MIN+min" "scalar_min(a, b)" +gen_binary_bcst_op_no_masked "MAX+max" "scalar_max(a, b)" gen_saturating_binary_op_associative "SUADD" "VectorMath.addSaturatingUnsigned(a, b)" "BITWISE" # Reductions. -gen_reduction_op "AND" "\&" "BITWISE" "AND_IDENTITY" -gen_reduction_op "OR" "|" "BITWISE" "OR_IDENTITY" -gen_reduction_op "XOR" "^" "BITWISE" "XOR_IDENTITY" -gen_reduction_op "ADD" "+" "" "ADD_IDENTITY" -gen_reduction_op "MUL" "*" "" "MUL_IDENTITY" -gen_reduction_op_func "MIN" "(\$type\$) Math.min" "" "MIN_IDENTITY" -gen_reduction_op_func "MAX" "(\$type\$) Math.max" "" "MAX_IDENTITY" +gen_reduction_op "AND" "scalar_and" "BITWISE" "AND_IDENTITY" +gen_reduction_op "OR" "scalar_or" "BITWISE" "OR_IDENTITY" +gen_reduction_op "XOR" "scalar_xor" "BITWISE" "XOR_IDENTITY" +gen_reduction_op "ADD" "scalar_add" "" "ADD_IDENTITY" +gen_reduction_op "MUL" "scalar_mul" "" "MUL_IDENTITY" +gen_reduction_op_func "MIN" "scalar_min" "" "MIN_IDENTITY" +gen_reduction_op_func "MAX" "scalar_max" "" "MAX_IDENTITY" gen_reduction_op_func "UMIN" "(\$type\$) VectorMath.minUnsigned" "BITWISE" "UMIN_IDENTITY" gen_reduction_op_func "UMAX" "(\$type\$) VectorMath.maxUnsigned" "BITWISE" "UMAX_IDENTITY" gen_reduction_op_func "FIRST_NONZERO" "firstNonZero" "" "FIRST_NONZERO_IDENTITY" @@ -535,9 +536,9 @@ gen_with_op "withLane" "" "" "" # Tests gen_op_tmpl $test_template "IS_DEFAULT" "bits(a)==0" gen_op_tmpl $test_template "IS_NEGATIVE" "bits(a)<0" -gen_op_tmpl $test_template "IS_FINITE" "\$Boxtype\$.isFinite(a)" "FP" -gen_op_tmpl $test_template "IS_NAN" "\$Boxtype\$.isNaN(a)" "FP" -gen_op_tmpl $test_template "IS_INFINITE" "\$Boxtype\$.isInfinite(a)" "FP" +gen_op_tmpl $test_template "IS_FINITE" "isFinite(a)" "FP" +gen_op_tmpl $test_template "IS_NAN" "isNaN(a)" "FP" +gen_op_tmpl $test_template "IS_INFINITE" "isInfinite(a)" "FP" # Compares gen_compare_op "LT+lt" "lt" @@ -553,8 +554,8 @@ gen_compare_op "ULE" "ule" "BITWISE" gen_compare_op "UGE" "uge" "BITWISE" -gen_compare_bcst_op "LT" "<" -gen_compare_bcst_op "EQ" "==" +gen_compare_bcst_op "LT" "lt" +gen_compare_bcst_op "EQ" "eq" # Blend. gen_op_tmpl $blend "blend" "" @@ -585,28 +586,28 @@ gen_op_tmpl $unslice1_template "unsliceBinary" "" gen_op_tmpl $unslice1_masked_template "unslice" "" # Math -gen_op_tmpl $unary_math_template "SIN" "Math.sin((double)a)" "FP" -gen_op_tmpl $unary_math_template "EXP" "Math.exp((double)a)" "FP" -gen_op_tmpl $unary_math_template "LOG1P" "Math.log1p((double)a)" "FP" -gen_op_tmpl $unary_math_template "LOG" "Math.log((double)a)" "FP" -gen_op_tmpl $unary_math_template "LOG10" "Math.log10((double)a)" "FP" -gen_op_tmpl $unary_math_template "EXPM1" "Math.expm1((double)a)" "FP" -gen_op_tmpl $unary_math_template "COS" "Math.cos((double)a)" "FP" -gen_op_tmpl $unary_math_template "TAN" "Math.tan((double)a)" "FP" -gen_op_tmpl $unary_math_template "SINH" "Math.sinh((double)a)" "FP" -gen_op_tmpl $unary_math_template "COSH" "Math.cosh((double)a)" "FP" -gen_op_tmpl $unary_math_template "TANH" "Math.tanh((double)a)" "FP" -gen_op_tmpl $unary_math_template "ASIN" "Math.asin((double)a)" "FP" -gen_op_tmpl $unary_math_template "ACOS" "Math.acos((double)a)" "FP" -gen_op_tmpl $unary_math_template "ATAN" "Math.atan((double)a)" "FP" -gen_op_tmpl $unary_math_template "CBRT" "Math.cbrt((double)a)" "FP" -gen_op_tmpl $binary_math_template "HYPOT" "Math.hypot((double)a, (double)b)" "FP" -gen_op_tmpl $binary_math_template "POW+pow" "Math.pow((double)a, (double)b)" "FP" -gen_op_tmpl $binary_math_template "ATAN2" "Math.atan2((double)a, (double)b)" "FP" -gen_op_tmpl $binary_math_broadcast_template "POW+pow" "Math.pow((double)a, (double)b)" "FP" +gen_op_tmpl $unary_math_template "SIN" "scalar_sin(a)" "FP" +gen_op_tmpl $unary_math_template "EXP" "scalar_exp(a)" "FP" +gen_op_tmpl $unary_math_template "LOG1P" "scalar_log1p(a)" "FP" +gen_op_tmpl $unary_math_template "LOG" "scalar_log(a)" "FP" +gen_op_tmpl $unary_math_template "LOG10" "scalar_log10(a)" "FP" +gen_op_tmpl $unary_math_template "EXPM1" "scalar_expm1(a)" "FP" +gen_op_tmpl $unary_math_template "COS" "scalar_cos(a)" "FP" +gen_op_tmpl $unary_math_template "TAN" "scalar_tan(a)" "FP" +gen_op_tmpl $unary_math_template "SINH" "scalar_sinh(a)" "FP" +gen_op_tmpl $unary_math_template "COSH" "scalar_cosh(a)" "FP" +gen_op_tmpl $unary_math_template "TANH" "scalar_tanh(a)" "FP" +gen_op_tmpl $unary_math_template "ASIN" "scalar_asin(a)" "FP" +gen_op_tmpl $unary_math_template "ACOS" "scalar_acos(a)" "FP" +gen_op_tmpl $unary_math_template "ATAN" "scalar_atan(a)" "FP" +gen_op_tmpl $unary_math_template "CBRT" "scalar_cbrt(a)" "FP" +gen_op_tmpl $binary_math_template "HYPOT" "scalar_hypot(a, b)" "FP" +gen_op_tmpl $binary_math_template "POW+pow" "scalar_pow(a, b)" "FP" +gen_op_tmpl $binary_math_template "ATAN2" "scalar_atan2(a, b)" "FP" +gen_op_tmpl $binary_math_broadcast_template "POW+pow" "scalar_pow(a, b)" "FP" # Ternary operations. -gen_ternary_alu_op "FMA+fma" "Math.fma(a, b, c)" "FP" +gen_ternary_alu_op "FMA+fma" "scalar_fma(a, b, c)" "FP" gen_ternary_alu_op "BITWISE_BLEND+bitwiseBlend" "(a\&~(c))|(b\&c)" "BITWISE" gen_ternary_alu_bcst_op "FMA" "Math.fma(a, b, c)" "FP" gen_ternary_alu_bcst_op "BITWISE_BLEND+bitwiseBlend" "(a\&~(c))|(b\&c)" "BITWISE" @@ -614,11 +615,11 @@ gen_ternary_alu_double_bcst_op "FMA+fma" "Math.fma(a, b, c)" "FP" gen_ternary_alu_double_bcst_op "BITWISE_BLEND+bitwiseBlend" "(a\&~(c))|(b\&c)" "BITWISE" # Unary operations. -gen_unary_alu_op "NEG+neg" "-((\$type\$)a)" -gen_unary_alu_op "ABS+abs" "Math.abs((\$type\$)a)" +gen_unary_alu_op "NEG+neg" "scalar_neg((\$type\$)a)" +gen_unary_alu_op "ABS+abs" "scalar_abs((\$type\$)a)" gen_unary_alu_op "NOT+not" "~((\$type\$)a)" "BITWISE" gen_unary_alu_op "ZOMO" "(a==0?0:-1)" "BITWISE" -gen_unary_alu_op "SQRT+sqrt" "Math.sqrt((double)a)" "FP" +gen_unary_alu_op "SQRT+sqrt" "scalar_sqrt(a)" "FP" gen_unary_alu_op "BIT_COUNT" "\$Boxtype\$.bitCount(a)" "intOrLong" gen_unary_alu_op "BIT_COUNT" "Integer.bitCount((int)a \& 0xFF)" "byte" gen_unary_alu_op "BIT_COUNT" "Integer.bitCount((int)a \& 0xFFFF)" "short" diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-op.template index 82e20d594b6..73e02bf68dd 100644 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-Masked-op.template @@ -10,7 +10,7 @@ $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); $type$ v = av.reduceLanes(VectorOperators.[[TEST]], vmask); r[i] = v; - ra [[TEST_OP]]= v; + ra = [[TEST_OP]](ra, v); } } diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-op.template index 3edc2b27e3e..94fae420cdd 100644 --- a/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-Reduction-op.template @@ -8,7 +8,7 @@ $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); $type$ v = av.reduceLanes(VectorOperators.[[TEST]]); r[i] = v; - ra [[TEST_OP]]= v; + ra = [[TEST_OP]](ra, v); } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Binary-op-math.template b/test/jdk/jdk/incubator/vector/templates/Unit-Binary-op-math.template index a3d44526db9..1866c28e2ba 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Binary-op-math.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Binary-op-math.template @@ -4,7 +4,7 @@ } static $type$ strict[[TEST]]($type$ a, $type$ b) { - return ($type$)(Strict[[TEST_OP]]); + return ($type$)(strict_[[TEST_OP]]); } @Test(dataProvider = "$type$BinaryOpProvider") diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template b/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template index 92e612e8184..faae74426e7 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Compare-Broadcast.template @@ -10,7 +10,7 @@ // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] [[TEST_OP]] b[i]); + assertEquals(mv.laneIsSet(j), [[TEST_OP]](a[i + j], b[i])); } } } @@ -30,7 +30,7 @@ // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] [[TEST_OP]] b[i])); + assertEquals(mv.laneIsSet(j), mask[j] && ([[TEST_OP]](a[i + j], b[i]))); } } } @@ -47,7 +47,7 @@ // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] [[TEST_OP]] ($type$)((long)b[i])); + assertEquals(mv.laneIsSet(j), [[TEST_OP]](a[i + j], ($type$)((long)b[i]))); } } } @@ -67,7 +67,7 @@ // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), mask[j] && (a[i + j] [[TEST_OP]] ($type$)((long)b[i]))); + assertEquals(mv.laneIsSet(j), mask[j] && ([[TEST_OP]](a[i + j], ($type$)((long)b[i])))); } } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template index 8411565628d..5ad7623d2c0 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template @@ -10,7 +10,7 @@ // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] < b[i]); + assertEquals(mv.laneIsSet(j), lt(a[i + j], b[i])); } } } @@ -26,7 +26,7 @@ // Check results as part of computation. for (int j = 0; j < SPECIES.length(); j++) { - assertEquals(mv.laneIsSet(j), a[i + j] == b[i]); + assertEquals(mv.laneIsSet(j), eq(a[i + j], b[i])); } } } @@ -123,7 +123,7 @@ static long ADDReduceLong($type$[] a, int idx) { $type$ res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res += a[i]; + res = scalar_add(res, a[i]); } return (long)res; @@ -132,7 +132,7 @@ static long ADDReduceAllLong($type$[] a) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLong(a, i); + res = (long)scalar_add(($type$)res, ($type$)ADDReduceLong(a, i)); } return res; @@ -150,8 +150,8 @@ } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add(($type$)ra, ($type$)r[i]); } assertReductionLongArraysEquals(r, ra, a, @@ -161,8 +161,9 @@ static long ADDReduceLongMasked($type$[] a, int idx, boolean[] mask) { $type$ res = 0; for (int i = idx; i < (idx + SPECIES.length()); i++) { - if(mask[i % SPECIES.length()]) - res += a[i]; + if (mask[i % SPECIES.length()]) { + res = scalar_add(res, a[i]); + } } return (long)res; @@ -171,7 +172,7 @@ static long ADDReduceAllLongMasked($type$[] a, boolean[] mask) { long res = 0; for (int i = 0; i < a.length; i += SPECIES.length()) { - res += ADDReduceLongMasked(a, i, mask); + res = (long)scalar_add(($type$)res, ($type$)ADDReduceLongMasked(a, i, mask)); } return res; @@ -191,8 +192,8 @@ } ra = 0; - for (int i = 0; i < a.length; i ++) { - ra += r[i]; + for (int i = 0; i < a.length; i++) { + ra = (long)scalar_add(($type$)ra, ($type$)r[i]); } assertReductionLongArraysEqualsMasked(r, ra, a, mask, diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-op.template index ab383e61256..1565c9f3551 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-Masked-op.template @@ -3,7 +3,7 @@ $type$ res = [[TEST_INIT]]; for (int i = idx; i < (idx + SPECIES.length()); i++) { if (mask[i % SPECIES.length()]) - res [[TEST_OP]]= a[i]; + res = [[TEST_OP]](res, a[i]); } return res; @@ -12,7 +12,7 @@ static $type$ [[TEST]]ReduceAllMasked($type$[] a, boolean[] mask) { $type$ res = [[TEST_INIT]]; for (int i = 0; i < a.length; i += SPECIES.length()) { - res [[TEST_OP]]= [[TEST]]ReduceMasked(a, i, mask); + res = [[TEST_OP]](res, [[TEST]]ReduceMasked(a, i, mask)); } return res; diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-op.template index 88586fa8129..63d154df112 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-Scalar-op.template @@ -2,7 +2,7 @@ static $type$ [[TEST]]Reduce($type$[] a, int idx) { $type$ res = [[TEST_INIT]]; for (int i = idx; i < (idx + SPECIES.length()); i++) { - res [[TEST_OP]]= a[i]; + res = [[TEST_OP]](res, a[i]); } return res; @@ -11,7 +11,7 @@ static $type$ [[TEST]]ReduceAll($type$[] a) { $type$ res = [[TEST_INIT]]; for (int i = 0; i < a.length; i += SPECIES.length()) { - res [[TEST_OP]]= [[TEST]]Reduce(a, i); + res = [[TEST_OP]](res, [[TEST]]Reduce(a, i)); } return res; diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-op.template index 25ae3ba2f12..d82b5533c4f 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-op.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Reduction-op.template @@ -15,20 +15,20 @@ $type$[] a = fa.apply(SPECIES.length()); $type$ id = [[TEST_INIT]]; - assertEquals(($type$) (id [[TEST_OP]] id), id, + assertEquals(($type$) ([[TEST_OP]](id, id)), id, "[[TEST]]([[TEST_INIT]], [[TEST_INIT]]) != [[TEST_INIT]]"); $type$ x = 0; try { for (int i = 0; i < a.length; i++) { x = a[i]; - assertEquals(($type$) (id [[TEST_OP]] x), x); - assertEquals(($type$) (x [[TEST_OP]] id), x); + assertEquals(($type$) ([[TEST_OP]](id, x)), x); + assertEquals(($type$) ([[TEST_OP]](x, id)), x); } } catch (AssertionError e) { - assertEquals(($type$) (id [[TEST_OP]] x), x, + assertEquals(($type$) ([[TEST_OP]](id, x)), x, "[[TEST]]([[TEST_INIT]], " + x + ") != " + x); - assertEquals(($type$) (x [[TEST_OP]] id), x, + assertEquals(($type$) ([[TEST_OP]](x, id)), x, "[[TEST]](" + x + ", [[TEST_INIT]]) != " + x); } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Unary-op-math.template b/test/jdk/jdk/incubator/vector/templates/Unit-Unary-op-math.template index 52293d9f614..f6943a0b40b 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Unary-op-math.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Unary-op-math.template @@ -4,7 +4,7 @@ } static $type$ strict[[TEST]]($type$ a) { - return ($type$)(Strict[[TEST_OP]]); + return ($type$)(strict_[[TEST_OP]]); } @Test(dataProvider = "$type$UnaryOpProvider") diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template index 00a7766492c..e1434dccb2b 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template @@ -1943,6 +1943,214 @@ relativeError)); static boolean ge($type$ a, $type$ b) { return a >= b; } + + static $type$ firstNonZero($type$ a, $type$ b) { + return $Wideboxtype$.compare(a, ($type$) 0) != 0 ? a : b; + } + +#if[BITWISE] + static $type$ scalar_or($type$ a, $type$ b) { + return ($type$)(a | b); + } + + static $type$ scalar_and($type$ a, $type$ b) { + return ($type$)(a & b); + } + + static $type$ scalar_xor($type$ a, $type$ b) { + return ($type$)(a ^ b); + } +#end[BITWISE]; + + static $type$ scalar_add($type$ a, $type$ b) { + return ($type$)(a + b); + } + + static $type$ scalar_sub($type$ a, $type$ b) { + return ($type$)(a - b); + } + + static $type$ scalar_mul($type$ a, $type$ b) { + return ($type$)(a * b); + } + + static $type$ scalar_min($type$ a, $type$ b) { + return ($type$)(Math.min(a, b)); + } + + static $type$ scalar_max($type$ a, $type$ b) { + return ($type$)(Math.max(a, b)); + } + + static $type$ scalar_div($type$ a, $type$ b) { + return ($type$)(a / b); + } + + static $type$ scalar_fma($type$ a, $type$ b, $type$ c) { + return ($type$)(Math.fma(a, b, c)); + } + + static $type$ scalar_abs($type$ a) { + return ($type$)(Math.abs(a)); + } + + static $type$ scalar_neg($type$ a) { + return (($type$)-a); + } + +#if[!BITWISE] + static $type$ scalar_sin($type$ a) { + return ($type$)Math.sin((double)a); + } + + static $type$ scalar_exp($type$ a) { + return ($type$)Math.exp((double)a); + } + + static $type$ scalar_log1p($type$ a) { + return ($type$)Math.log1p((double)a); + } + + static $type$ scalar_log($type$ a) { + return ($type$)Math.log((double)a); + } + + static $type$ scalar_log10($type$ a) { + return ($type$)Math.log10((double)a); + } + + static $type$ scalar_expm1($type$ a) { + return ($type$)Math.expm1((double)a); + } + + static $type$ scalar_cos($type$ a) { + return ($type$)Math.cos((double)a); + } + + static $type$ scalar_tan($type$ a) { + return ($type$)Math.tan((double)a); + } + + static $type$ scalar_sinh($type$ a) { + return ($type$)Math.sinh((double)a); + } + + static $type$ scalar_cosh($type$ a) { + return ($type$)Math.cosh((double)a); + } + + static $type$ scalar_tanh($type$ a) { + return ($type$)Math.tanh((double)a); + } + + static $type$ scalar_asin($type$ a) { + return ($type$)Math.asin((double)a); + } + + static $type$ scalar_acos($type$ a) { + return ($type$)Math.acos((double)a); + } + + static $type$ scalar_atan($type$ a) { + return ($type$)Math.atan((double)a); + } + + static $type$ scalar_cbrt($type$ a) { + return ($type$)Math.cbrt((double)a); + } + + static $type$ scalar_sqrt($type$ a) { + return ($type$)Math.sqrt((double)a); + } + + static $type$ scalar_hypot($type$ a, $type$ b) { + return ($type$)Math.hypot((double)a, (double)b); + } + + static $type$ scalar_pow($type$ a, $type$ b) { + return ($type$)Math.pow((double)a, (double)b); + } + + static $type$ scalar_atan2($type$ a, $type$ b) { + return ($type$)Math.atan2((double)a, (double)b); + } + + static $type$ strict_scalar_sin($type$ a) { + return ($type$)StrictMath.sin((double)a); + } + + static $type$ strict_scalar_exp($type$ a) { + return ($type$)StrictMath.exp((double)a); + } + + static $type$ strict_scalar_log1p($type$ a) { + return ($type$)StrictMath.log1p((double)a); + } + + static $type$ strict_scalar_log($type$ a) { + return ($type$)StrictMath.log((double)a); + } + + static $type$ strict_scalar_log10($type$ a) { + return ($type$)StrictMath.log10((double)a); + } + + static $type$ strict_scalar_expm1($type$ a) { + return ($type$)StrictMath.expm1((double)a); + } + + static $type$ strict_scalar_cos($type$ a) { + return ($type$)StrictMath.cos((double)a); + } + + static $type$ strict_scalar_tan($type$ a) { + return ($type$)StrictMath.tan((double)a); + } + + static $type$ strict_scalar_sinh($type$ a) { + return ($type$)StrictMath.sinh((double)a); + } + + static $type$ strict_scalar_cosh($type$ a) { + return ($type$)StrictMath.cosh((double)a); + } + + static $type$ strict_scalar_tanh($type$ a) { + return ($type$)StrictMath.tanh((double)a); + } + + static $type$ strict_scalar_asin($type$ a) { + return ($type$)StrictMath.asin((double)a); + } + + static $type$ strict_scalar_acos($type$ a) { + return ($type$)StrictMath.acos((double)a); + } + + static $type$ strict_scalar_atan($type$ a) { + return ($type$)StrictMath.atan((double)a); + } + + static $type$ strict_scalar_cbrt($type$ a) { + return ($type$)StrictMath.cbrt((double)a); + } + + static $type$ strict_scalar_sqrt($type$ a) { + return ($type$)StrictMath.sqrt((double)a); + } + + static $type$ strict_scalar_hypot($type$ a, $type$ b) { + return ($type$)StrictMath.hypot((double)a, (double)b); + } + + static $type$ strict_scalar_pow($type$ a, $type$ b) { + return ($type$)StrictMath.pow((double)a, (double)b); + } + + static $type$ strict_scalar_atan2($type$ a, $type$ b) { + return ($type$)StrictMath.atan2((double)a, (double)b); + } +#end[!BITWISE] #if[!FP] static boolean ult($type$ a, $type$ b) { @@ -1962,9 +2170,17 @@ relativeError)); } #end[!FP] - static $type$ firstNonZero($type$ a, $type$ b) { - return $Boxtype$.compare(a, ($type$) 0) != 0 ? a : b; +#if[FP] + static boolean isNaN($type$ a) { + return $Wideboxtype$.isNaN(a); } + static boolean isFinite($type$ a) { + return $Wideboxtype$.isFinite(a); + } + static boolean isInfinite($type$ a) { + return $Wideboxtype$.isInfinite(a); + } +#end[FP] @Test static void smokeTest1() { From 310d5a15628f7efde06e2680a92a979de3a233b5 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 6 Mar 2026 04:39:42 +0000 Subject: [PATCH 087/170] 8346256: Optimize UMIN/UMAX reduction operations for x86 targets Reviewed-by: qamai, sviswanathan --- src/hotspot/cpu/x86/assembler_x86.cpp | 7 +++ src/hotspot/cpu/x86/assembler_x86.hpp | 1 + src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 48 ++++++++++++++++++- src/hotspot/cpu/x86/x86.ad | 24 ++++++++++ .../vectorapi/VectorUMinMaxReductionTest.java | 33 ++++++------- 5 files changed, 95 insertions(+), 18 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 3c8defe62d9..38a28a6ec49 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -5442,6 +5442,13 @@ void Assembler::pmovsxwd(XMMRegister dst, XMMRegister src) { emit_int16(0x23, (0xC0 | encode)); } +void Assembler::pmovzxwd(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sse4_1(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x33, (0xC0 | encode)); +} + void Assembler::vpmovzxbw(XMMRegister dst, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 97854f712cf..57a5e25d7a6 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1965,6 +1965,7 @@ private: void pmovsxbq(XMMRegister dst, XMMRegister src); void pmovsxbw(XMMRegister dst, XMMRegister src); void pmovsxwd(XMMRegister dst, XMMRegister src); + void pmovzxwd(XMMRegister dst, XMMRegister src); void vpmovsxbd(XMMRegister dst, XMMRegister src, int vector_len); void vpmovsxbq(XMMRegister dst, XMMRegister src, int vector_len); void vpmovsxbw(XMMRegister dst, XMMRegister src, int vector_len); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index a3ccc081b6b..5b5fb02967c 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -1729,6 +1729,24 @@ void C2_MacroAssembler::reduce_operation_128(BasicType typ, int opcode, XMMRegis default: assert(false, "wrong type"); } break; + case Op_UMinReductionV: + switch (typ) { + case T_BYTE: vpminub(dst, dst, src, Assembler::AVX_128bit); break; + case T_SHORT: vpminuw(dst, dst, src, Assembler::AVX_128bit); break; + case T_INT: vpminud(dst, dst, src, Assembler::AVX_128bit); break; + case T_LONG: evpminuq(dst, k0, dst, src, true, Assembler::AVX_128bit); break; + default: assert(false, "wrong type"); + } + break; + case Op_UMaxReductionV: + switch (typ) { + case T_BYTE: vpmaxub(dst, dst, src, Assembler::AVX_128bit); break; + case T_SHORT: vpmaxuw(dst, dst, src, Assembler::AVX_128bit); break; + case T_INT: vpmaxud(dst, dst, src, Assembler::AVX_128bit); break; + case T_LONG: evpmaxuq(dst, k0, dst, src, true, Assembler::AVX_128bit); break; + default: assert(false, "wrong type"); + } + break; case Op_AddReductionVF: addss(dst, src); break; case Op_AddReductionVD: addsd(dst, src); break; case Op_AddReductionVI: @@ -1792,6 +1810,24 @@ void C2_MacroAssembler::reduce_operation_256(BasicType typ, int opcode, XMMRegis default: assert(false, "wrong type"); } break; + case Op_UMinReductionV: + switch (typ) { + case T_BYTE: vpminub(dst, src1, src2, vector_len); break; + case T_SHORT: vpminuw(dst, src1, src2, vector_len); break; + case T_INT: vpminud(dst, src1, src2, vector_len); break; + case T_LONG: evpminuq(dst, k0, src1, src2, true, vector_len); break; + default: assert(false, "wrong type"); + } + break; + case Op_UMaxReductionV: + switch (typ) { + case T_BYTE: vpmaxub(dst, src1, src2, vector_len); break; + case T_SHORT: vpmaxuw(dst, src1, src2, vector_len); break; + case T_INT: vpmaxud(dst, src1, src2, vector_len); break; + case T_LONG: evpmaxuq(dst, k0, src1, src2, true, vector_len); break; + default: assert(false, "wrong type"); + } + break; case Op_AddReductionVI: switch (typ) { case T_BYTE: vpaddb(dst, src1, src2, vector_len); break; @@ -2058,7 +2094,11 @@ void C2_MacroAssembler::reduce8B(int opcode, Register dst, Register src1, XMMReg psrldq(vtmp2, 1); reduce_operation_128(T_BYTE, opcode, vtmp1, vtmp2); movdl(vtmp2, src1); - pmovsxbd(vtmp1, vtmp1); + if (opcode == Op_UMinReductionV || opcode == Op_UMaxReductionV) { + pmovzxbd(vtmp1, vtmp1); + } else { + pmovsxbd(vtmp1, vtmp1); + } reduce_operation_128(T_INT, opcode, vtmp1, vtmp2); pextrb(dst, vtmp1, 0x0); movsbl(dst, dst); @@ -2135,7 +2175,11 @@ void C2_MacroAssembler::reduce4S(int opcode, Register dst, Register src1, XMMReg reduce_operation_128(T_SHORT, opcode, vtmp1, vtmp2); } movdl(vtmp2, src1); - pmovsxwd(vtmp1, vtmp1); + if (opcode == Op_UMinReductionV || opcode == Op_UMaxReductionV) { + pmovzxwd(vtmp1, vtmp1); + } else { + pmovsxwd(vtmp1, vtmp1); + } reduce_operation_128(T_INT, opcode, vtmp1, vtmp2); pextrw(dst, vtmp1, 0x0); movswl(dst, dst); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 0ffa4c2031c..b155355c827 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -3341,6 +3341,18 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { return false; } break; + case Op_UMinReductionV: + case Op_UMaxReductionV: + if (UseAVX == 0) { + return false; + } + if (bt == T_LONG && !VM_Version::supports_avx512vl()) { + return false; + } + if (UseAVX > 2 && size_in_bits == 512 && !VM_Version::supports_avx512vl()) { + return false; + } + break; case Op_MaxV: case Op_MinV: if (UseSSE < 4 && is_integral_type(bt)) { @@ -19371,6 +19383,8 @@ instruct reductionI(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtm match(Set dst (XorReductionV src1 src2)); match(Set dst (MinReductionV src1 src2)); match(Set dst (MaxReductionV src1 src2)); + match(Set dst (UMinReductionV src1 src2)); + match(Set dst (UMaxReductionV src1 src2)); effect(TEMP vtmp1, TEMP vtmp2); format %{ "vector_reduction_int $dst,$src1,$src2 ; using $vtmp1, $vtmp2 as TEMP" %} ins_encode %{ @@ -19392,6 +19406,8 @@ instruct reductionL(rRegL dst, rRegL src1, legVec src2, legVec vtmp1, legVec vtm match(Set dst (XorReductionV src1 src2)); match(Set dst (MinReductionV src1 src2)); match(Set dst (MaxReductionV src1 src2)); + match(Set dst (UMinReductionV src1 src2)); + match(Set dst (UMaxReductionV src1 src2)); effect(TEMP vtmp1, TEMP vtmp2); format %{ "vector_reduction_long $dst,$src1,$src2 ; using $vtmp1, $vtmp2 as TEMP" %} ins_encode %{ @@ -19411,6 +19427,8 @@ instruct reductionL_avx512dq(rRegL dst, rRegL src1, vec src2, vec vtmp1, vec vtm match(Set dst (XorReductionV src1 src2)); match(Set dst (MinReductionV src1 src2)); match(Set dst (MaxReductionV src1 src2)); + match(Set dst (UMinReductionV src1 src2)); + match(Set dst (UMaxReductionV src1 src2)); effect(TEMP vtmp1, TEMP vtmp2); format %{ "vector_reduction_long $dst,$src1,$src2 ; using $vtmp1, $vtmp2 as TEMP" %} ins_encode %{ @@ -19639,6 +19657,8 @@ instruct reductionB(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtm match(Set dst (XorReductionV src1 src2)); match(Set dst (MinReductionV src1 src2)); match(Set dst (MaxReductionV src1 src2)); + match(Set dst (UMinReductionV src1 src2)); + match(Set dst (UMaxReductionV src1 src2)); effect(TEMP vtmp1, TEMP vtmp2); format %{ "vector_reduction_byte $dst,$src1,$src2 ; using $vtmp1, $vtmp2 as TEMP" %} ins_encode %{ @@ -19657,6 +19677,8 @@ instruct reductionB_avx512bw(rRegI dst, rRegI src1, vec src2, vec vtmp1, vec vtm match(Set dst (XorReductionV src1 src2)); match(Set dst (MinReductionV src1 src2)); match(Set dst (MaxReductionV src1 src2)); + match(Set dst (UMinReductionV src1 src2)); + match(Set dst (UMaxReductionV src1 src2)); effect(TEMP vtmp1, TEMP vtmp2); format %{ "vector_reduction_byte $dst,$src1,$src2 ; using $vtmp1, $vtmp2 as TEMP" %} ins_encode %{ @@ -19678,6 +19700,8 @@ instruct reductionS(rRegI dst, rRegI src1, legVec src2, legVec vtmp1, legVec vtm match(Set dst (XorReductionV src1 src2)); match(Set dst (MinReductionV src1 src2)); match(Set dst (MaxReductionV src1 src2)); + match(Set dst (UMinReductionV src1 src2)); + match(Set dst (UMaxReductionV src1 src2)); effect(TEMP vtmp1, TEMP vtmp2); format %{ "vector_reduction_short $dst,$src1,$src2 ; using $vtmp1, $vtmp2 as TEMP" %} ins_encode %{ diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorUMinMaxReductionTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorUMinMaxReductionTest.java index 1c8cc34170e..4c753d91afd 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorUMinMaxReductionTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorUMinMaxReductionTest.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -140,7 +141,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testByteUMin() { byte got = ByteVector.fromArray(B_SPECIES, ba, 0).reduceLanes(VectorOperators.UMIN); verifyByte(B_SPECIES, got, BYTE_UMIN_IDENTITY, VectorMath::minUnsigned, false); @@ -148,7 +149,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testByteUMax() { byte got = ByteVector.fromArray(B_SPECIES, ba, 0).reduceLanes(VectorOperators.UMAX); verifyByte(B_SPECIES, got, BYTE_UMAX_IDENTITY, VectorMath::maxUnsigned, false); @@ -156,7 +157,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testByteUMinMasked() { byte got = ByteVector.fromArray(B_SPECIES, ba, 0) .reduceLanes(VectorOperators.UMIN, @@ -166,7 +167,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testByteUMaxMasked() { byte got = ByteVector.fromArray(B_SPECIES, ba, 0) .reduceLanes(VectorOperators.UMAX, @@ -178,7 +179,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testShortUMin() { short got = ShortVector.fromArray(S_SPECIES, sa, 0).reduceLanes(VectorOperators.UMIN); verifyShort(S_SPECIES, got, SHORT_UMIN_IDENTITY, VectorMath::minUnsigned, false); @@ -186,7 +187,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testShortUMax() { short got = ShortVector.fromArray(S_SPECIES, sa, 0).reduceLanes(VectorOperators.UMAX); verifyShort(S_SPECIES, got, SHORT_UMAX_IDENTITY, VectorMath::maxUnsigned, false); @@ -194,7 +195,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testShortUMinMasked() { short got = ShortVector.fromArray(S_SPECIES, sa, 0) .reduceLanes(VectorOperators.UMIN, @@ -204,7 +205,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testShortUMaxMasked() { short got = ShortVector.fromArray(S_SPECIES, sa, 0) .reduceLanes(VectorOperators.UMAX, @@ -216,7 +217,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testIntUMin() { int got = IntVector.fromArray(I_SPECIES, ia, 0).reduceLanes(VectorOperators.UMIN); verifyInt(I_SPECIES, got, INT_UMIN_IDENTITY, VectorMath::minUnsigned, false); @@ -224,7 +225,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testIntUMax() { int got = IntVector.fromArray(I_SPECIES, ia, 0).reduceLanes(VectorOperators.UMAX); verifyInt(I_SPECIES, got, INT_UMAX_IDENTITY, VectorMath::maxUnsigned, false); @@ -232,7 +233,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testIntUMinMasked() { int got = IntVector.fromArray(I_SPECIES, ia, 0) .reduceLanes(VectorOperators.UMIN, @@ -242,7 +243,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}) public static void testIntUMaxMasked() { int got = IntVector.fromArray(I_SPECIES, ia, 0) .reduceLanes(VectorOperators.UMAX, @@ -254,7 +255,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx512vl", "true"}) public static void testLongUMin() { long got = LongVector.fromArray(L_SPECIES, la, 0).reduceLanes(VectorOperators.UMIN); verifyLong(L_SPECIES, got, LONG_UMIN_IDENTITY, VectorMath::minUnsigned, false); @@ -262,7 +263,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx512vl", "true"}) public static void testLongUMax() { long got = LongVector.fromArray(L_SPECIES, la, 0).reduceLanes(VectorOperators.UMAX); verifyLong(L_SPECIES, got, LONG_UMAX_IDENTITY, VectorMath::maxUnsigned, false); @@ -270,7 +271,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMIN_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx512vl", "true"}) public static void testLongUMinMasked() { long got = LongVector.fromArray(L_SPECIES, la, 0) .reduceLanes(VectorOperators.UMIN, @@ -280,7 +281,7 @@ public class VectorUMinMaxReductionTest { @Test @IR(counts = {IRNode.UMAX_REDUCTION_V, "= 1"}, - applyIfCPUFeature = {"asimd", "true"}) + applyIfCPUFeatureOr = {"asimd", "true", "avx512vl", "true"}) public static void testLongUMaxMasked() { long got = LongVector.fromArray(L_SPECIES, la, 0) .reduceLanes(VectorOperators.UMAX, From a2ad0809899f4f31c4bead58bcb441451403d6e8 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Fri, 6 Mar 2026 07:15:13 +0000 Subject: [PATCH 088/170] 8379326: Use JUnit in lib-test/jdk tests, here MethodTemplateTest Reviewed-by: dfuchs, rriggs --- test/lib-test/TEST.ROOT | 3 +++ .../jdk/test/lib/jittester/MethodTemplateTest.java | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/test/lib-test/TEST.ROOT b/test/lib-test/TEST.ROOT index f23d38c1e66..33c9a9c2a43 100644 --- a/test/lib-test/TEST.ROOT +++ b/test/lib-test/TEST.ROOT @@ -31,6 +31,9 @@ keys=randomness # Minimum jtreg version requiredVersion=8.2.1+1 +# Prevent TestNG-based tests under this root, use @run junit actions instead +disallowedActions=testng + # Allow querying of various System properties in @requires clauses requires.extraPropDefns = ../jtreg-ext/requires/VMProps.java requires.extraPropDefns.bootlibs = ../lib/jdk/test/whitebox diff --git a/test/lib-test/jdk/test/lib/jittester/MethodTemplateTest.java b/test/lib-test/jdk/test/lib/jittester/MethodTemplateTest.java index 3cee24b4684..69751bc281c 100644 --- a/test/lib-test/jdk/test/lib/jittester/MethodTemplateTest.java +++ b/test/lib-test/jdk/test/lib/jittester/MethodTemplateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ package jdk.test.lib.jittester; import java.lang.reflect.Executable; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; /* * @test @@ -35,7 +35,7 @@ import static org.testng.Assert.*; * @library /test/lib * /test/hotspot/jtreg/testlibrary/jittester/src * - * @run testng jdk.test.lib.jittester.MethodTemplateTest + * @run junit jdk.test.lib.jittester.MethodTemplateTest */ public class MethodTemplateTest { From dc6f7014aa3791a5a6fd2b89ac19d88382c16da2 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 6 Mar 2026 09:04:54 +0000 Subject: [PATCH 089/170] 8379202: Support linktime-gc on Linux with clang Reviewed-by: jwaters, clanger, erikj --- make/autoconf/flags-cflags.m4 | 5 +++++ make/autoconf/flags-ldflags.m4 | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 2d39d84f52e..ab9cd8be19b 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -578,6 +578,11 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], TOOLCHAIN_CFLAGS_JDK_CONLY="-fno-strict-aliasing" # technically NOT for CXX fi + if test "x$ENABLE_LINKTIME_GC" = xtrue; then + TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -ffunction-sections -fdata-sections" + TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections" + fi + if test "x$OPENJDK_TARGET_OS" = xaix; then TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -ftls-model -fno-math-errno" TOOLCHAIN_CFLAGS_JDK="-ffunction-sections -fsigned-char" diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index 466ff1beaf4..7782735be25 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -80,6 +80,10 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], if test "x$CXX_IS_USER_SUPPLIED" = xfalse && test "x$CC_IS_USER_SUPPLIED" = xfalse; then UTIL_REQUIRE_TOOLCHAIN_PROGS(LLD, lld) fi + + if test "x$ENABLE_LINKTIME_GC" = xtrue; then + BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections" + fi fi if test "x$OPENJDK_TARGET_OS" = xaix; then BASIC_LDFLAGS="-Wl,-b64 -Wl,-brtl -Wl,-bnorwexec -Wl,-blibpath:/usr/lib:lib -Wl,-bnoexpall \ From ca479be7470af4124d666d63f5cbef101c4db5d2 Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Fri, 6 Mar 2026 10:21:14 +0000 Subject: [PATCH 090/170] 8379363: FontInfo improvements Reviewed-by: prr, serb --- .../classes/sun/java2d/loops/FontInfo.java | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/java.desktop/share/classes/sun/java2d/loops/FontInfo.java b/src/java.desktop/share/classes/sun/java2d/loops/FontInfo.java index 09aa05b785e..10e10a4adde 100644 --- a/src/java.desktop/share/classes/sun/java2d/loops/FontInfo.java +++ b/src/java.desktop/share/classes/sun/java2d/loops/FontInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.java2d.loops; import java.awt.Font; +import java.util.Arrays; import sun.font.Font2D; import sun.font.FontStrike; @@ -41,7 +42,7 @@ import sun.font.FontStrike; * time. I am reluctant to add the overhead of that machinery here without * a proven benefit. */ -public class FontInfo implements Cloneable { +public final class FontInfo implements Cloneable { public Font font; public Font2D font2D; public FontStrike fontStrike; @@ -56,15 +57,7 @@ public class FontInfo implements Cloneable { /* lcdSubPixPos is used if FM is ON for HRGB/HBGR LCD text mode */ public boolean lcdSubPixPos; - public String mtx(double[] matrix) { - return ("["+ - matrix[0]+", "+ - matrix[1]+", "+ - matrix[2]+", "+ - matrix[3]+ - "]"); - } - + @Override public Object clone() { try { return super.clone(); @@ -73,15 +66,16 @@ public class FontInfo implements Cloneable { } } + @Override public String toString() { return ("FontInfo["+ "font="+font+", "+ - "devTx="+mtx(devTx)+", "+ - "glyphTx="+mtx(glyphTx)+", "+ + "devTx="+Arrays.toString(devTx)+", "+ + "glyphTx="+Arrays.toString(glyphTx)+", "+ "pixelHeight="+pixelHeight+", "+ "origin=("+originX+","+originY+"), "+ "aaHint="+aaHint+", "+ - "lcdRGBOrder="+(lcdRGBOrder ? "RGB" : "BGR")+ + "lcdRGBOrder="+(lcdRGBOrder ? "RGB" : "BGR")+", "+ "lcdSubPixPos="+lcdSubPixPos+ "]"); } From 45fc141d29161e6957e95604a3a79dc6c0f7a830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Fri, 6 Mar 2026 10:23:33 +0000 Subject: [PATCH 091/170] 8379230: JFR: Do not store leak context edge idx in markWord Reviewed-by: egahlin --- .../jfr/leakprofiler/chains/edgeStore.cpp | 80 +++++++------------ .../jfr/leakprofiler/chains/edgeStore.hpp | 3 +- 2 files changed, 31 insertions(+), 52 deletions(-) diff --git a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp index 9aef92c4182..2c341f2385e 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,10 @@ #include "jfr/leakprofiler/chains/edgeUtils.hpp" #include "jfr/leakprofiler/sampling/objectSample.hpp" #include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp" +#include "jfr/recorder/service/jfrOptionSet.hpp" #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" +#include "utilities/resizableHashTable.hpp" StoredEdge::StoredEdge(const Edge* parent, UnifiedOopRef reference) : Edge(parent, reference), _gc_root_id(0), _skip_length(0) {} @@ -216,84 +218,62 @@ bool EdgeStore::put_edges(StoredEdge** previous, const Edge** current, size_t li return nullptr == *current; } -static GrowableArray* _leak_context_edges = nullptr; +typedef ResizeableHashTable SampleToLeakContextEdgeMap; +static SampleToLeakContextEdgeMap* _sample_to_leak_context_edge_map = nullptr; EdgeStore::EdgeStore() : _edges(new EdgeHashTable(this)) {} EdgeStore::~EdgeStore() { assert(_edges != nullptr, "invariant"); delete _edges; - delete _leak_context_edges; - _leak_context_edges = nullptr; + delete _sample_to_leak_context_edge_map; + _sample_to_leak_context_edge_map = nullptr; } -static int leak_context_edge_idx(const ObjectSample* sample) { +static const StoredEdge* leak_context_edge(const ObjectSample* sample) { assert(sample != nullptr, "invariant"); - return static_cast(sample->object()->mark().value()) >> markWord::lock_bits; + assert(_sample_to_leak_context_edge_map != nullptr, "invariant"); + const StoredEdge** edge = _sample_to_leak_context_edge_map->get(p2u(sample->object())); + return edge != nullptr ? *edge : nullptr; } bool EdgeStore::has_leak_context(const ObjectSample* sample) const { - const int idx = leak_context_edge_idx(sample); - if (idx == 0) { - return false; - } - assert(idx > 0, "invariant"); - assert(_leak_context_edges != nullptr, "invariant"); - assert(idx < _leak_context_edges->length(), "invariant"); - assert(_leak_context_edges->at(idx) != nullptr, "invariant"); - return true; + return _sample_to_leak_context_edge_map != nullptr && leak_context_edge(sample) != nullptr; } const StoredEdge* EdgeStore::get(const ObjectSample* sample) const { assert(sample != nullptr, "invariant"); - if (_leak_context_edges != nullptr) { + if (_sample_to_leak_context_edge_map != nullptr) { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); - const int idx = leak_context_edge_idx(sample); - if (idx > 0) { - assert(idx < _leak_context_edges->length(), "invariant"); - const StoredEdge* const edge =_leak_context_edges->at(idx); - assert(edge != nullptr, "invariant"); + const StoredEdge* const edge = leak_context_edge(sample); + if (edge != nullptr) { return edge; } } return get(UnifiedOopRef::encode_in_native(sample->object_addr())); } -#ifdef ASSERT -// max_idx to ensure idx fit in lower 32-bits of markword together with lock bits. -static constexpr const int max_idx = right_n_bits(32 - markWord::lock_bits); +static constexpr const unsigned max_map_size = max_jint >> 1; -static void store_idx_precondition(oop sample_object, int idx) { - assert(sample_object != nullptr, "invariant"); - assert(sample_object->mark().is_marked(), "invariant"); - assert(idx > 0, "invariant"); - assert(idx <= max_idx, "invariant"); -} -#endif - -static void store_idx_in_markword(oop sample_object, int idx) { - DEBUG_ONLY(store_idx_precondition(sample_object, idx);) - const markWord idx_mark_word(sample_object->mark().value() | idx << markWord::lock_bits); - sample_object->set_mark(idx_mark_word); - assert(sample_object->mark().is_marked(), "must still be marked"); -} - -static const int initial_size = 64; - -static int save(const StoredEdge* edge) { - assert(edge != nullptr, "invariant"); - if (_leak_context_edges == nullptr) { - _leak_context_edges = new (mtTracing) GrowableArray(initial_size, mtTracing); - _leak_context_edges->append(nullptr); // next idx now at 1, for disambiguation in markword. +static inline unsigned map_size() { + assert(JfrOptionSet::old_object_queue_size() > 0, "invariant"); + unsigned size = JfrOptionSet::old_object_queue_size(); + size = round_up_power_of_2(size); + if (size < 1024) { + return 1024; } - return _leak_context_edges->append(edge); + size <<= 1; + return size >= max_map_size ? max_map_size : size; } -// We associate the leak context edge with the leak candidate object by saving the -// edge in an array and storing the array idx (shifted) into the markword of the candidate object. static void associate_with_candidate(const StoredEdge* leak_context_edge) { assert(leak_context_edge != nullptr, "invariant"); - store_idx_in_markword(leak_context_edge->pointee(), save(leak_context_edge)); + if (_sample_to_leak_context_edge_map == nullptr) { + const unsigned size = map_size(); + _sample_to_leak_context_edge_map = new (mtTracing) SampleToLeakContextEdgeMap(size, size); + } + assert(_sample_to_leak_context_edge_map != nullptr, "invariant"); + _sample_to_leak_context_edge_map->put(p2u(leak_context_edge->pointee()), leak_context_edge); } StoredEdge* EdgeStore::associate_leak_context_with_candidate(const Edge* edge) { diff --git a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp index e920fd64ea9..460314854b7 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ class StoredEdge : public Edge { size_t _skip_length; public: - StoredEdge(); StoredEdge(const Edge* parent, UnifiedOopRef reference); StoredEdge(const Edge& edge); StoredEdge(const StoredEdge& edge); From 374a94f447b5849afa217dbd83607225e984b378 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Fri, 6 Mar 2026 14:26:09 +0000 Subject: [PATCH 092/170] 8379201: Wrong type annotation offset on casts on expressions (redo) Reviewed-by: jlahoda --- .../com/sun/tools/javac/comp/TransTypes.java | 24 ++- .../IncorrectCastOffsetTest.java | 178 ++++++++++++++++++ 2 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java 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 862c02ea5f0..1229939c0bf 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 @@ -29,7 +29,6 @@ package com.sun.tools.javac.comp; import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.TypeCompound; -import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.TypeVar; import com.sun.tools.javac.jvm.Target; @@ -49,8 +48,6 @@ import static com.sun.tools.javac.code.TypeTag.VOID; import static com.sun.tools.javac.comp.CompileStates.CompileState; import com.sun.tools.javac.tree.JCTree.JCBreak; -import javax.lang.model.type.TypeKind; - /** This pass translates Generic Java to conventional Java. * *

    This is NOT part of any supported API. @@ -109,7 +106,9 @@ public class TransTypes extends TreeTranslator { if (!types.isSameType(tree.type, target)) { if (!resolve.isAccessible(env, target.tsym)) resolve.logAccessErrorInternal(env, tree, target); - tree = make.TypeCast(make.Type(target), tree).setType(target); + tree = explicitCastTP != null && types.isSameType(target, explicitCastTP) ? + tree : + make.TypeCast(make.Type(target), tree).setType(target); } make.pos = oldpos; return tree; @@ -440,16 +439,29 @@ public class TransTypes extends TreeTranslator { /** Visitor argument: proto-type. */ private Type pt; + /** we use this type to indicate that "upstream" there is an explicit cast to this type, + * this way we can avoid generating redundant type casts. Redundant casts are not + * innocuous as they can trump user provided ones and affect the offset + * calculation of type annotations applied to the user provided type cast. + */ + private Type explicitCastTP; /** Visitor method: perform a type translation on tree. */ public T translate(T tree, Type pt) { + return translate(tree, pt, pt == explicitCastTP ? explicitCastTP : null); + } + + public T translate(T tree, Type pt, Type castTP) { Type prevPt = this.pt; + Type prevCastPT = this.explicitCastTP; try { this.pt = pt; + this.explicitCastTP = castTP; return translate(tree); } finally { this.pt = prevPt; + this.explicitCastTP = prevCastPT; } } @@ -1037,7 +1049,9 @@ public class TransTypes extends TreeTranslator { tree.clazz = translate(tree.clazz, null); Type originalTarget = tree.type; tree.type = erasure(tree.type); - JCExpression newExpression = translate(tree.expr, tree.type); + JCExpression newExpression = tree.clazz.hasTag(Tag.ANNOTATED_TYPE) ? + translate(tree.expr, tree.type, tree.type) : + translate(tree.expr, tree.type); if (newExpression != tree.expr) { JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST) ? (JCTypeCast) newExpression diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java new file mode 100644 index 00000000000..7a00cf1c897 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/IncorrectCastOffsetTest.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8214934 8379201 + * @summary Wrong type annotation offset on casts on expressions + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.ToolBox toolbox.JavapTask + * @run compile -g:none IncorrectCastOffsetTest.java + * @run main IncorrectCastOffsetTest + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import java.util.List; + +import toolbox.JavapTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class IncorrectCastOffsetTest { + @Target(ElementType.TYPE_USE) + @Retention(RetentionPolicy.RUNTIME) + @interface TypeUse {} + + @Target(ElementType.TYPE_USE) + @Retention(RetentionPolicy.RUNTIME) + @interface TypeUse2 {} + + class AnnotatedCast1 { + private static String checkcast(boolean test, Object obj, Object obj2) { + return (@TypeUse String)(test ? obj : obj2); + } + } + + class AnnotatedCast2 { + private static String checkcast(Object obj) { + return (@TypeUse String)(obj); + } + } + + class AnnotatedCast3 { + private static String checkcast(boolean test, Object obj, Object obj2) { + return (@TypeUse @TypeUse2 String)(test ? obj : obj2); + } + } + + class AnnotatedCast4 { + private static String checkcast(Object obj) { + return (@TypeUse String)(@TypeUse2 CharSequence)(obj); + } + } + + ToolBox tb; + + IncorrectCastOffsetTest() { + tb = new ToolBox(); + } + + public static void main(String args[]) { + IncorrectCastOffsetTest incorrectCastOffsetTest = new IncorrectCastOffsetTest(); + incorrectCastOffsetTest.run(); + } + + void run() { + test("IncorrectCastOffsetTest$AnnotatedCast1.class", + /* + * generated code: + * 0: iload_0 + * 1: ifeq 8 + * 4: aload_1 + * 5: goto 9 + * 8: aload_2 + * 9: checkcast #13 // class java/lang/String + * 12: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #24(): CAST, offset=9, type_index=0", + "IncorrectCastOffsetTest$TypeUse" + ) + ); + test("IncorrectCastOffsetTest$AnnotatedCast2.class", + /* + * generated code: + * 0: aload_0 + * 1: checkcast #13 // class java/lang/String + * 4: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #23(): CAST, offset=1, type_index=0", + "IncorrectCastOffsetTest$TypeUse" + ) + ); + test("IncorrectCastOffsetTest$AnnotatedCast3.class", + /* + * generated code: + * 0: iload_0 + * 1: ifeq 8 + * 4: aload_1 + * 5: goto 9 + * 8: aload_2 + * 9: checkcast #13 // class java/lang/String + * 12: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #24(): CAST, offset=9, type_index=0", + "IncorrectCastOffsetTest$TypeUse", + "1: #25(): CAST, offset=9, type_index=0", + "IncorrectCastOffsetTest$TypeUse2" + ) + ); + test("IncorrectCastOffsetTest$AnnotatedCast4.class", + /* + * generated code: + * 0: aload_0 + * 1: checkcast #13 // class java/lang/CharSequence + * 4: checkcast #15 // class java/lang/String + * 7: areturn + */ + List.of( + "RuntimeVisibleTypeAnnotations:", + "0: #25(): CAST, offset=4, type_index=0", + "IncorrectCastOffsetTest$TypeUse", + "1: #26(): CAST, offset=1, type_index=0", + "IncorrectCastOffsetTest$TypeUse2" + ) + ); + } + + void test(String clazz, List expectedOutput) { + Path pathToClass = Paths.get(ToolBox.testClasses, clazz); + String javapOut = new JavapTask(tb) + .options("-v", "-p") + .classes(pathToClass.toString()) + .run() + .getOutput(Task.OutputKind.DIRECT); + + for (String expected : expectedOutput) { + if (!javapOut.contains(expected)) { + throw new AssertionError("unexpected output"); + } + } + } + +} From b349f661ea5f14b258191134714a7e712c90ef3e Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Fri, 6 Mar 2026 14:27:53 +0000 Subject: [PATCH 093/170] 8379191: SunX509KeyManagerImpl alias chooser methods returns null for EC_EC Reviewed-by: myankelevich, mullan --- .../ssl/X509KeyManagerCertChecking.java | 6 +- .../X509KeyManager/SelfSignedCertKeyType.java | 131 ++++++++++++++++++ 2 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 test/jdk/sun/security/ssl/X509KeyManager/SelfSignedCertKeyType.java diff --git a/src/java.base/share/classes/sun/security/ssl/X509KeyManagerCertChecking.java b/src/java.base/share/classes/sun/security/ssl/X509KeyManagerCertChecking.java index 6d26558847c..e0203128962 100644 --- a/src/java.base/share/classes/sun/security/ssl/X509KeyManagerCertChecking.java +++ b/src/java.base/share/classes/sun/security/ssl/X509KeyManagerCertChecking.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -512,13 +512,13 @@ abstract class X509KeyManagerCertChecking extends X509ExtendedKeyManager { chain[1].getPublicKey().getAlgorithm()); } else { // Check the signature algorithm of the certificate itself. - // Look for the "withRSA" in "SHA1withRSA", etc. + // Look for the "withEC" in "SHA256withECDSA", etc. X509Certificate issuer = (X509Certificate) chain[0]; String sigAlgName = issuer.getSigAlgName().toUpperCase(Locale.ENGLISH); String pattern = "WITH" + sigKeyAlgorithm.toUpperCase(Locale.ENGLISH); - return sigAlgName.endsWith(pattern); + return sigAlgName.contains(pattern); } } } diff --git a/test/jdk/sun/security/ssl/X509KeyManager/SelfSignedCertKeyType.java b/test/jdk/sun/security/ssl/X509KeyManager/SelfSignedCertKeyType.java new file mode 100644 index 00000000000..2395020de08 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509KeyManager/SelfSignedCertKeyType.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertNotNull; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.X509ExtendedKeyManager; +import jdk.test.lib.security.CertificateBuilder; + +/* + * @test + * @bug 8379191 + * @summary SunX509KeyManagerImpl alias chooser methods returns null for EC_EC + * @modules java.base/sun.security.x509 + * java.base/sun.security.util + * @library /test/lib + * @run main SelfSignedCertKeyType SunX509 + * @run main SelfSignedCertKeyType PKIX + */ + +public class SelfSignedCertKeyType { + + private static final String CERT_ALIAS = "testalias"; + private static final String KEY_ALG = "EC"; + private static final String KEY_TYPE = "EC_EC"; + private static final String CERT_SIG_ALG = "SHA256withECDSA"; + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + throw new RuntimeException("Wrong number of arguments"); + } + + X509ExtendedKeyManager km = getKeyManager(args[0]); + + String serverAlias = km.chooseServerAlias(KEY_TYPE, null, null); + String engineServerAlias = km.chooseEngineServerAlias( + KEY_TYPE, null, null); + String clientAlias = km.chooseClientAlias( + new String[]{KEY_TYPE}, null, null); + String engineClientAlias = km.chooseEngineClientAlias( + new String[]{KEY_TYPE}, null, null); + + for (String alias : new String[]{serverAlias, + engineServerAlias, clientAlias, engineClientAlias}) { + assertNotNull(alias); + assertEquals(CERT_ALIAS, normalizeAlias(alias)); + } + } + + // PKIX KeyManager adds a cache prefix to an alias. + private static String normalizeAlias(String alias) { + return alias.substring(alias.lastIndexOf(".") + 1); + } + + // Returns a KeyManager with a single self-signed certificate. + private static X509ExtendedKeyManager getKeyManager(String kmAlg) + throws Exception { + KeyPair caKeys = KeyPairGenerator.getInstance(KEY_ALG) + .generateKeyPair(); + X509Certificate trustedCert = createTrustedCert(caKeys); + + // create a key store + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(null, null); + + // import the trusted cert + ks.setCertificateEntry("TLS Signer", trustedCert); + + // generate certificate chain + Certificate[] chain = new Certificate[1]; + chain[0] = trustedCert; + + // import the key entry. + final char[] passphrase = "passphrase".toCharArray(); + ks.setKeyEntry(CERT_ALIAS, caKeys.getPrivate(), passphrase, chain); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmAlg); + kmf.init(ks, passphrase); + + return (X509ExtendedKeyManager) kmf.getKeyManagers()[0]; + } + + private static X509Certificate createTrustedCert(KeyPair caKeys) + throws Exception { + return new CertificateBuilder() + .setSubjectName("O=CA-Org, L=Some-City, ST=Some-State, C=US") + .setPublicKey(caKeys.getPublic()) + .setNotBefore( + Date.from(Instant.now().minus(1, ChronoUnit.HOURS))) + .setNotAfter(Date.from(Instant.now().plus(1, ChronoUnit.HOURS))) + .setSerialNumber(BigInteger.valueOf( + new SecureRandom().nextLong(1000000) + 1)) + .addSubjectKeyIdExt(caKeys.getPublic()) + .addAuthorityKeyIdExt(caKeys.getPublic()) + .addKeyUsageExt(new boolean[]{ + true, true, true, true, true, true, true}) + .addBasicConstraintsExt(true, true, 1) + .build(null, caKeys.getPrivate(), CERT_SIG_ALG); + } +} From 0aa52d633a72a240a22c55fb14d9e9744d2cd675 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 6 Mar 2026 15:39:27 +0000 Subject: [PATCH 094/170] 8379371: Proposed cleanups for JDK-8373595 A new ObjectMonitorTable implementation Reviewed-by: stefank, fbredberg --- src/hotspot/share/prims/jvmtiEnvBase.cpp | 2 +- src/hotspot/share/runtime/deoptimization.cpp | 2 +- .../share/runtime/lockStack.inline.hpp | 4 +- src/hotspot/share/runtime/objectMonitor.cpp | 2 +- .../share/runtime/objectMonitorTable.cpp | 27 +++++----- .../share/runtime/objectMonitorTable.hpp | 6 +-- src/hotspot/share/runtime/synchronizer.cpp | 52 +++++++++---------- src/hotspot/share/runtime/synchronizer.hpp | 14 ++--- src/hotspot/share/runtime/vframe.cpp | 4 +- src/hotspot/share/services/threadService.cpp | 2 +- 10 files changed, 58 insertions(+), 57 deletions(-) diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 401bb4dfdb8..886c2da1dee 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1529,7 +1529,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec GrowableArray* wantList = nullptr; ObjectMonitor* mon = mark.has_monitor() - ? ObjectSynchronizer::read_monitor(current_thread, hobj(), mark) + ? ObjectSynchronizer::read_monitor(hobj(), mark) : nullptr; if (mon != nullptr) { diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 54a65358693..5fbe2842a2b 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1686,7 +1686,7 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArrayowner()->is_locked(), "object must be locked now"); assert(obj->mark().has_monitor(), "must be"); assert(!deoptee_thread->lock_stack().contains(obj()), "must be"); - assert(ObjectSynchronizer::read_monitor(thread, obj(), obj->mark())->has_owner(deoptee_thread), "must be"); + assert(ObjectSynchronizer::read_monitor(obj(), obj->mark())->has_owner(deoptee_thread), "must be"); } } } diff --git a/src/hotspot/share/runtime/lockStack.inline.hpp b/src/hotspot/share/runtime/lockStack.inline.hpp index 27eb07fcec8..a9ad3553db8 100644 --- a/src/hotspot/share/runtime/lockStack.inline.hpp +++ b/src/hotspot/share/runtime/lockStack.inline.hpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2022, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,7 +254,7 @@ inline void OMCache::set_monitor(ObjectMonitor *monitor) { oop obj = monitor->object_peek(); assert(obj != nullptr, "must be alive"); - assert(monitor == ObjectSynchronizer::get_monitor_from_table(JavaThread::current(), obj), "must exist in table"); + assert(monitor == ObjectSynchronizer::get_monitor_from_table(obj), "must exist in table"); OMCacheEntry to_insert = {obj, monitor}; diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 91771772e2c..cb69b82d767 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -854,7 +854,7 @@ bool ObjectMonitor::deflate_monitor(Thread* current) { } if (UseObjectMonitorTable) { - ObjectSynchronizer::deflate_monitor(current, obj, this); + ObjectSynchronizer::deflate_monitor(obj, this); } else if (obj != nullptr) { // Install the old mark word if nobody else has already done it. install_displaced_markword_in_object(obj); diff --git a/src/hotspot/share/runtime/objectMonitorTable.cpp b/src/hotspot/share/runtime/objectMonitorTable.cpp index 767f5de6897..8431b6dd0d4 100644 --- a/src/hotspot/share/runtime/objectMonitorTable.cpp +++ b/src/hotspot/share/runtime/objectMonitorTable.cpp @@ -46,7 +46,7 @@ // // When you want to find a monitor associated with an object, you extract the // hash value of the object. Then calculate an index by taking the hash value -// and bit-wise AND it with the capacity mask (e.g. size-1) of the OMT. Now +// and bit-wise AND it with the capacity mask (i.e., size-1) of the OMT. Now // use that index into the OMT's array of pointers. If the pointer is non // null, check if it's a monitor pointer that is associated with the object. // If so you're done. If the pointer is non null, but associated with another @@ -55,7 +55,7 @@ // means that the monitor is simply not in the OMT. // // If the size of the pointer array is significantly larger than the number of -// pointers in it, the chance of finding the monitor in the hash index +// pointers in it, the chance of finding the monitor at the hash index // (without any further linear searching) is quite high. It is also straight // forward to generate C2 code for this, which for the fast path doesn't // contain any branching at all. See: C2_MacroAssembler::fast_lock(). @@ -69,10 +69,10 @@ // old monitor pointers from the old table to the new. // // But since the OMT is a concurrent hash table and things needs to work for -// other clients of the OMT while we grow it, it's gets a bit more +// other clients of the OMT while we grow it, it gets a bit more // complicated. // -// Both the new and (potentially several) old table(s) may exist at the same +// The new and (potentially several) old table(s) may exist at the same // time. The newest is always called the "current", and the older ones are // singly linked using a "prev" pointer. // @@ -82,7 +82,8 @@ // // After that we start to go through all the indexes in the old table. If the // index is empty (the pointer is null) we put a "tombstone" into that index, -// which will prevent any future concurrent insert ending up in that index. +// which will prevent any future concurrent insert from ending up in that +// index. // // If the index contains a monitor pointer, we insert that monitor pointer // into the OMT which can be considered as one generation newer. If the index @@ -92,11 +93,11 @@ // that is not null, not a tombstone and not removed, is considered to be a // pointer to a monitor. // -// When all the monitor pointers from an old OMT has been transferred to the +// When all the monitor pointers from an old OMT have been transferred to the // new OMT, the old table is unlinked. // // This copying from an old OMT to one generation newer OMT, will continue -// until all the monitor pointers from old OMTs has been transferred to the +// until all the monitor pointers from old OMTs have been transferred to the // newest "current" OMT. // // The memory for old, unlinked OMTs will be freed after a thread-local @@ -255,7 +256,7 @@ public: } ObjectMonitor* prepare_insert(oop obj, intptr_t hash) { - // Acquire any tomb stones and relocations if prev transitioned to null. + // Acquire any tombstones and relocations if prev transitioned to null. Table* prev = AtomicAccess::load_acquire(&_prev); if (prev != nullptr) { ObjectMonitor* result = prev->prepare_insert(obj, hash); @@ -273,7 +274,7 @@ public: if (entry == empty()) { // Found an empty slot to install the new monitor in. - // To avoid concurrent inserts succeeding, place a tomb stone here. + // To avoid concurrent inserts succeeding, place a tombstone here. Entry result = AtomicAccess::cmpxchg(bucket, entry, tombstone(), memory_order_relaxed); if (result == entry) { // Success! Nobody will try to insert here again, except reinsert from rehashing. @@ -515,7 +516,7 @@ void ObjectMonitorTable::create() { _curr = new Table(128, nullptr); } -ObjectMonitor* ObjectMonitorTable::monitor_get(Thread* current, oop obj) { +ObjectMonitor* ObjectMonitorTable::monitor_get(oop obj) { const intptr_t hash = obj->mark().hash(); Table* curr = AtomicAccess::load_acquire(&_curr); ObjectMonitor* monitor = curr->get(obj, hash); @@ -562,7 +563,7 @@ ObjectMonitorTable::Table* ObjectMonitorTable::grow_table(Table* curr) { return result; } -ObjectMonitor* ObjectMonitorTable::monitor_put_get(Thread* current, ObjectMonitor* monitor, oop obj) { +ObjectMonitor* ObjectMonitorTable::monitor_put_get(ObjectMonitor* monitor, oop obj) { const intptr_t hash = obj->mark().hash(); Table* curr = AtomicAccess::load_acquire(&_curr); @@ -577,7 +578,7 @@ ObjectMonitor* ObjectMonitorTable::monitor_put_get(Thread* current, ObjectMonito } } -void ObjectMonitorTable::remove_monitor_entry(Thread* current, ObjectMonitor* monitor) { +void ObjectMonitorTable::remove_monitor_entry(ObjectMonitor* monitor) { oop obj = monitor->object_peek(); if (obj == nullptr) { // Defer removal until subsequent rebuilding. @@ -586,7 +587,7 @@ void ObjectMonitorTable::remove_monitor_entry(Thread* current, ObjectMonitor* mo const intptr_t hash = obj->mark().hash(); Table* curr = AtomicAccess::load_acquire(&_curr); curr->remove(obj, curr->as_entry(monitor), hash); - assert(monitor_get(current, obj) != monitor, "should have been removed"); + assert(monitor_get(obj) != monitor, "should have been removed"); } // Before handshake; rehash and unlink tables. diff --git a/src/hotspot/share/runtime/objectMonitorTable.hpp b/src/hotspot/share/runtime/objectMonitorTable.hpp index e8e7c61c6fa..0a56b696069 100644 --- a/src/hotspot/share/runtime/objectMonitorTable.hpp +++ b/src/hotspot/share/runtime/objectMonitorTable.hpp @@ -61,11 +61,11 @@ public: } SpecialPointerValues; static void create(); - static ObjectMonitor* monitor_get(Thread* current, oop obj); - static ObjectMonitor* monitor_put_get(Thread* current, ObjectMonitor* monitor, oop obj); + static ObjectMonitor* monitor_get(oop obj); + static ObjectMonitor* monitor_put_get(ObjectMonitor* monitor, oop obj); static void rebuild(GrowableArray* delete_list); static void destroy(GrowableArray* delete_list); - static void remove_monitor_entry(Thread* current, ObjectMonitor* monitor); + static void remove_monitor_entry(ObjectMonitor* monitor); // Compiler support static address current_table_address(); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index c93e1a65512..8ea5fe31145 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -350,7 +350,7 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool al } if (mark.has_monitor()) { - ObjectMonitor* const mon = read_monitor(current, obj, mark); + ObjectMonitor* const mon = read_monitor(obj, mark); if (mon == nullptr) { // Racing with inflation/deflation go slow path return false; @@ -485,7 +485,7 @@ ObjectLocker::ObjectLocker(Handle obj, TRAPS) : _thread(THREAD), _obj(obj), // otherwise just force other vthreads to preempt in case they try // to acquire this monitor. _skip_exit = !_thread->preemption_cancelled(); - ObjectSynchronizer::read_monitor(_thread, _obj())->set_object_strong(); + ObjectSynchronizer::read_monitor(_obj())->set_object_strong(); _thread->set_pending_preempted_exception(); } @@ -502,7 +502,7 @@ void ObjectLocker::wait_uninterruptibly(TRAPS) { ObjectSynchronizer::waitUninterruptibly(_obj, 0, _thread); if (_thread->preempting()) { _skip_exit = true; - ObjectSynchronizer::read_monitor(_thread, _obj())->set_object_strong(); + ObjectSynchronizer::read_monitor(_obj())->set_object_strong(); _thread->set_pending_preempted_exception(); } } @@ -749,7 +749,7 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current, } while (mark.has_monitor()) { - ObjectMonitor* monitor = read_monitor(current, obj, mark); + ObjectMonitor* monitor = read_monitor(obj, mark); if (monitor != nullptr) { return monitor->is_entered(current) != 0; } @@ -778,7 +778,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob } while (mark.has_monitor()) { - ObjectMonitor* monitor = read_monitor(Thread::current(), obj, mark); + ObjectMonitor* monitor = read_monitor(obj, mark); if (monitor != nullptr) { return Threads::owning_thread_from_monitor(t_list, monitor); } @@ -1425,7 +1425,7 @@ void ObjectSynchronizer::chk_in_use_entry(ObjectMonitor* n, outputStream* out, return; } - ObjectMonitor* const obj_mon = read_monitor(Thread::current(), obj, mark); + ObjectMonitor* const obj_mon = read_monitor(obj, mark); if (n != obj_mon) { out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use monitor's " "object does not refer to the same monitor: obj=" @@ -1471,8 +1471,8 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream* out, bool log_ out->flush(); } -ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor_from_table(oop object, JavaThread* current, bool* inserted) { - ObjectMonitor* monitor = get_monitor_from_table(current, object); +ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor_from_table(oop object, bool* inserted) { + ObjectMonitor* monitor = get_monitor_from_table(object); if (monitor != nullptr) { *inserted = false; return monitor; @@ -1482,7 +1482,7 @@ ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor_from_table(oop object, alloced_monitor->set_anonymous_owner(); // Try insert monitor - monitor = add_monitor(current, alloced_monitor, object); + monitor = add_monitor(alloced_monitor, object); *inserted = alloced_monitor == monitor; if (!*inserted) { @@ -1522,7 +1522,7 @@ ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor(oop object, JavaThread* EventJavaMonitorInflate event; bool inserted; - ObjectMonitor* monitor = get_or_insert_monitor_from_table(object, current, &inserted); + ObjectMonitor* monitor = get_or_insert_monitor_from_table(object, &inserted); if (inserted) { log_inflate(current, object, cause); @@ -1538,7 +1538,7 @@ ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor(oop object, JavaThread* } // Add the hashcode to the monitor to match the object and put it in the hashtable. -ObjectMonitor* ObjectSynchronizer::add_monitor(JavaThread* current, ObjectMonitor* monitor, oop obj) { +ObjectMonitor* ObjectSynchronizer::add_monitor(ObjectMonitor* monitor, oop obj) { assert(UseObjectMonitorTable, "must be"); assert(obj == monitor->object(), "must be"); @@ -1546,14 +1546,14 @@ ObjectMonitor* ObjectSynchronizer::add_monitor(JavaThread* current, ObjectMonito assert(hash != 0, "must be set when claiming the object monitor"); monitor->set_hash(hash); - return ObjectMonitorTable::monitor_put_get(current, monitor, obj); + return ObjectMonitorTable::monitor_put_get(monitor, obj); } -void ObjectSynchronizer::remove_monitor(Thread* current, ObjectMonitor* monitor, oop obj) { +void ObjectSynchronizer::remove_monitor(ObjectMonitor* monitor, oop obj) { assert(UseObjectMonitorTable, "must be"); assert(monitor->object_peek() == obj, "must be, cleared objects are removed by is_dead"); - ObjectMonitorTable::remove_monitor_entry(current, monitor); + ObjectMonitorTable::remove_monitor_entry(monitor); } void ObjectSynchronizer::deflate_mark_word(oop obj) { @@ -1721,7 +1721,7 @@ bool ObjectSynchronizer::fast_lock_spin_enter(oop obj, LockStack& lock_stack, Ja return true; } else if (observed_deflation) { // Spin while monitor is being deflated. - ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(current, obj, mark); + ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj, mark); return monitor == nullptr || monitor->is_being_async_deflated(); } // Else stop spinning. @@ -1881,7 +1881,7 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) if (UseObjectMonitorTable) { monitor = read_caches(current, lock, object); if (monitor == nullptr) { - monitor = get_monitor_from_table(current, object); + monitor = get_monitor_from_table(object); } } else { monitor = ObjectSynchronizer::read_monitor(mark); @@ -1925,7 +1925,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_locked_or_imse(oop obj, ObjectSynchro } assert(mark.has_monitor(), "must be"); - ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(current, obj, mark); + ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj, mark); if (monitor != nullptr) { if (monitor->has_anonymous_owner()) { LockStack& lock_stack = current->lock_stack(); @@ -2087,7 +2087,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_fast_locked_object(oop object, Object // contains a deflating monitor it must be anonymously owned. if (monitor->has_anonymous_owner()) { // The monitor must be anonymously owned if it was added - assert(monitor == get_monitor_from_table(current, object), "The monitor must be found"); + assert(monitor == get_monitor_from_table(object), "The monitor must be found"); // New fresh monitor break; } @@ -2279,31 +2279,31 @@ ObjectMonitor* ObjectSynchronizer::inflate_and_enter(oop object, BasicLock* lock return monitor; } -void ObjectSynchronizer::deflate_monitor(Thread* current, oop obj, ObjectMonitor* monitor) { +void ObjectSynchronizer::deflate_monitor(oop obj, ObjectMonitor* monitor) { if (obj != nullptr) { deflate_mark_word(obj); - remove_monitor(current, monitor, obj); + remove_monitor(monitor, obj); } } -ObjectMonitor* ObjectSynchronizer::get_monitor_from_table(Thread* current, oop obj) { +ObjectMonitor* ObjectSynchronizer::get_monitor_from_table(oop obj) { assert(UseObjectMonitorTable, "must be"); - return ObjectMonitorTable::monitor_get(current, obj); + return ObjectMonitorTable::monitor_get(obj); } ObjectMonitor* ObjectSynchronizer::read_monitor(markWord mark) { return mark.monitor(); } -ObjectMonitor* ObjectSynchronizer::read_monitor(Thread* current, oop obj) { - return ObjectSynchronizer::read_monitor(current, obj, obj->mark()); +ObjectMonitor* ObjectSynchronizer::read_monitor(oop obj) { + return ObjectSynchronizer::read_monitor(obj, obj->mark()); } -ObjectMonitor* ObjectSynchronizer::read_monitor(Thread* current, oop obj, markWord mark) { +ObjectMonitor* ObjectSynchronizer::read_monitor(oop obj, markWord mark) { if (!UseObjectMonitorTable) { return read_monitor(mark); } else { - return ObjectSynchronizer::get_monitor_from_table(current, obj); + return ObjectSynchronizer::get_monitor_from_table(obj); } } diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp index 97690b9c886..58d0e88a026 100644 --- a/src/hotspot/share/runtime/synchronizer.hpp +++ b/src/hotspot/share/runtime/synchronizer.hpp @@ -126,8 +126,8 @@ public: static const char* inflate_cause_name(const InflateCause cause); static ObjectMonitor* read_monitor(markWord mark); - static ObjectMonitor* read_monitor(Thread* current, oop obj); - static ObjectMonitor* read_monitor(Thread* current, oop obj, markWord mark); + static ObjectMonitor* read_monitor(oop obj); + static ObjectMonitor* read_monitor(oop obj, markWord mark); // Returns the identity hash value for an oop // NOTE: It may cause monitor inflation @@ -209,11 +209,11 @@ public: static void handle_sync_on_value_based_class(Handle obj, JavaThread* locking_thread); - static ObjectMonitor* get_or_insert_monitor_from_table(oop object, JavaThread* current, bool* inserted); + static ObjectMonitor* get_or_insert_monitor_from_table(oop object, bool* inserted); static ObjectMonitor* get_or_insert_monitor(oop object, JavaThread* current, ObjectSynchronizer::InflateCause cause); - static ObjectMonitor* add_monitor(JavaThread* current, ObjectMonitor* monitor, oop obj); - static void remove_monitor(Thread* current, ObjectMonitor* monitor, oop obj); + static ObjectMonitor* add_monitor(ObjectMonitor* monitor, oop obj); + static void remove_monitor(ObjectMonitor* monitor, oop obj); static void deflate_mark_word(oop object); @@ -239,9 +239,9 @@ public: static ObjectMonitor* inflate_fast_locked_object(oop object, ObjectSynchronizer::InflateCause cause, JavaThread* locking_thread, JavaThread* current); static ObjectMonitor* inflate_and_enter(oop object, BasicLock* lock, ObjectSynchronizer::InflateCause cause, JavaThread* locking_thread, JavaThread* current); - static void deflate_monitor(Thread* current, oop obj, ObjectMonitor* monitor); + static void deflate_monitor(oop obj, ObjectMonitor* monitor); - static ObjectMonitor* get_monitor_from_table(Thread* current, oop obj); + static ObjectMonitor* get_monitor_from_table(oop obj); static bool contains_monitor(Thread* current, ObjectMonitor* monitor); diff --git a/src/hotspot/share/runtime/vframe.cpp b/src/hotspot/share/runtime/vframe.cpp index 604ff1f751a..c9628255e45 100644 --- a/src/hotspot/share/runtime/vframe.cpp +++ b/src/hotspot/share/runtime/vframe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,7 +248,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, bool is_virtual, int frame // The first stage of async deflation does not affect any field // used by this comparison so the ObjectMonitor* is usable here. if (mark.has_monitor()) { - ObjectMonitor* mon = ObjectSynchronizer::read_monitor(current, monitor->owner(), mark); + ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner(), mark); if (// if the monitor is null we must be in the process of locking mon == nullptr || // we have marked ourself as pending on this monitor diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp index 4f511075967..35c7de48d2e 100644 --- a/src/hotspot/share/services/threadService.cpp +++ b/src/hotspot/share/services/threadService.cpp @@ -1252,7 +1252,7 @@ private: // The first stage of async deflation does not affect any field // used by this comparison so the ObjectMonitor* is usable here. if (mark.has_monitor()) { - ObjectMonitor* mon = ObjectSynchronizer::read_monitor(current, monitor->owner(), mark); + ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner(), mark); if (// if the monitor is null we must be in the process of locking mon == nullptr || // we have marked ourself as pending on this monitor From ea4a1512456d29d05a634c14bb2beb65152ba1f4 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 6 Mar 2026 17:20:44 +0000 Subject: [PATCH 095/170] 8379156: Specify behavior of Types.asElement() on array types Reviewed-by: hannesw, liach --- .../classes/javax/lang/model/util/Types.java | 1 + .../model/util/types/TestAsElement.java | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Types.java b/src/java.compiler/share/classes/javax/lang/model/util/Types.java index e7212a7e0be..f632135a899 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/Types.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/Types.java @@ -74,6 +74,7 @@ public interface Types { * Types without corresponding elements include: *

      *
    • {@linkplain TypeKind#isPrimitive() primitive types} + *
    • {@linkplain TypeKind#ARRAY array types} *
    • {@linkplain TypeKind#EXECUTABLE executable types} *
    • {@linkplain TypeKind#NONE "none"} pseudo-types *
    • {@linkplain TypeKind#NULL null types} diff --git a/test/langtools/tools/javac/processing/model/util/types/TestAsElement.java b/test/langtools/tools/javac/processing/model/util/types/TestAsElement.java index 6ac714752c3..cc82c5adddd 100644 --- a/test/langtools/tools/javac/processing/model/util/types/TestAsElement.java +++ b/test/langtools/tools/javac/processing/model/util/types/TestAsElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8300857 + * @bug 8300857 8379156 * @summary Test Types.asElement in cases specified to return null * @library /tools/javac/lib * @build JavacTestingAbstractProcessor TestAsElement @@ -55,18 +55,23 @@ public class TestAsElement extends JavacTestingAbstractProcessor { } private void testNullCases() { - // Test all primitive types + // Test all primitive types and arrays of primitive types for (TypeKind typeKind : TypeKind.values()) { if (typeKind.isPrimitive() ) { - expectNullAsElement(typeUtils.getPrimitiveType(typeKind)); + var primType = typeUtils.getPrimitiveType(typeKind); + expectNullAsElement(primType); + expectNullAsElement(typeUtils.getArrayType(primType)); } } expectNullAsElement(typeUtils.getNoType(TypeKind.VOID)); expectNullAsElement(typeUtils.getNoType(TypeKind.NONE)); expectNullAsElement(typeUtils.getNullType()); - Element objectElement = eltUtils.getTypeElement("java.lang.Object"); - expectNullAsElement(typeUtils.getWildcardType(objectElement.asType(), null)); + Element objectElement = eltUtils.getTypeElement("java.lang.Object"); + TypeMirror objectType = objectElement.asType(); + expectNullAsElement(typeUtils.getWildcardType(objectType, null)); + // check Object[] + expectNullAsElement(typeUtils.getArrayType(objectType)); // Loop over the ExecutableTypes for Object's methods for(var methodElt : ElementFilter.methodsIn(objectElement.getEnclosedElements())) { From 779970fb6fdae8b12ca29b4887d2812c50835653 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 6 Mar 2026 17:57:32 +0000 Subject: [PATCH 096/170] 8373626: [asan] read past end of buffer in sun.awt.image.ImagingLib.convolveBI Reviewed-by: jdv --- .../libmlib_image/mlib_ImageConv_16nw.c | 116 +++++++++++++++--- .../libmlib_image/mlib_ImageConv_32nw.c | 59 +++++++-- .../native/libmlib_image/mlib_ImageConv_8nw.c | 116 +++++++++++++++--- .../libmlib_image/mlib_ImageConv_D64nw.c | 56 +++++++-- .../libmlib_image/mlib_ImageConv_F32nw.c | 53 ++++++-- .../libmlib_image/mlib_ImageConv_u16nw.c | 116 +++++++++++++++--- .../libmlib_image/mlib_c_ImageConvVersion.c | 4 +- 7 files changed, 425 insertions(+), 95 deletions(-) diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c index 2e035d12453..26686e59b0b 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_16nw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -286,13 +286,14 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, pk = k + off; sp = sl0; - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; - dp = dl; kh = n - off; if (kh == 4) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; + sp += 3*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -325,6 +326,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 3) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + p2 = sp[0]; p3 = sp[sll]; + sp += 2*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -357,6 +362,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 2) { + + k0 = pk[0]; k1 = pk[1]; + p2 = sp[0]; + sp += sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -389,6 +398,9 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else /* if (kh == 1) */ { + + k0 = pk[0]; + for (j = 0; j < hsize; j++) { p0 = sp[0]; @@ -536,15 +548,14 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, sp = sl; dp = dl; - p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; - p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - pk += kw; - if (kw == 7) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; p5 = p7; @@ -583,6 +594,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 6) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; @@ -618,6 +635,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 5) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; @@ -653,6 +676,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; @@ -688,6 +715,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 3) { + p2 = buff[0]; p3 = buff[1]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; @@ -723,6 +754,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else /*if (kw == 2)*/ { + p2 = buff[0]; + + k0 = pk[0]; k1 = pk[1]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; @@ -756,6 +791,8 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } } + + pk += kw; } } @@ -882,17 +919,16 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, if (kw > MAX_KER) kw = kw/2; off += kw; - p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; - p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; p7 = sp[5*chan1]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - pk += kw; - - sp += (kw - 1)*chan1; - if (kw == 7) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; p7 = sp[5*chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; p5 = p7; @@ -927,6 +963,14 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 6) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; @@ -961,6 +1005,14 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 5) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; @@ -995,6 +1047,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; @@ -1029,6 +1087,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 3) { + p2 = sp[0]; p3 = sp[chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; @@ -1063,6 +1127,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 2) { + p2 = sp[0]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; @@ -1097,6 +1167,10 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else /*if (kw == 1)*/ { + k0 = pk[0]; + + sp += (kw - 1)*chan1; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = sp[0]; @@ -1127,6 +1201,8 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } } } + + pk += kw; } } diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c index bb264d9dcd2..b2ee9742213 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_32nw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -158,13 +158,14 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, pk = k + off; sp = sl0; - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; - dp = dl; kh = n - off; if (kh == 4) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; + sp += 3*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -195,6 +196,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 3) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + p2 = sp[0]; p3 = sp[sll]; + sp += 2*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -225,6 +230,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 2) { + + k0 = pk[0]; k1 = pk[1]; + p2 = sp[0]; + sp += sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -255,6 +264,9 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else /* if (kh == 1) */ { + + k0 = pk[0]; + for (j = 0; j < hsize; j++) { p0 = sp[0]; @@ -400,15 +412,14 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, sp = sl; dp = dl; - p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; - p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - pk += kw; - if (kw == 7) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; p5 = p7; @@ -444,6 +455,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 6) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; @@ -479,6 +496,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 5) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; @@ -514,6 +537,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; @@ -549,6 +576,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 3) { + p2 = buff[0]; p3 = buff[1]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; @@ -584,6 +615,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else { /* kw == 2 */ + p2 = buff[0]; + + k0 = pk[0]; k1 = pk[1]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; @@ -617,6 +652,8 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } } + + pk += kw; } } diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c index c144404b0f4..ce7cac00f72 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_8nw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -287,13 +287,14 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, pk = k + off; sp = sl0; - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; - dp = dl; kh = n - off; if (kh == 4) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; + sp += 3*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -326,6 +327,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 3) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + p2 = sp[0]; p3 = sp[sll]; + sp += 2*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -358,6 +363,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 2) { + + k0 = pk[0]; k1 = pk[1]; + p2 = sp[0]; + sp += sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -390,6 +399,9 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else /* if (kh == 1) */ { + + k0 = pk[0]; + for (j = 0; j < hsize; j++) { p0 = sp[0]; @@ -537,15 +549,14 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, sp = sl; dp = dl; - p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; - p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - pk += kw; - if (kw == 7) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; p5 = p7; @@ -584,6 +595,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 6) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; @@ -619,6 +636,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 5) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; @@ -654,6 +677,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; @@ -689,6 +716,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 3) { + p2 = buff[0]; p3 = buff[1]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; @@ -724,6 +755,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else /*if (kw == 2)*/ { + p2 = buff[0]; + + k0 = pk[0]; k1 = pk[1]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; @@ -757,6 +792,8 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } } + + pk += kw; } } @@ -883,17 +920,16 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, if (kw > MAX_KER) kw = kw/2; off += kw; - p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; - p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; p7 = sp[5*chan1]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - pk += kw; - - sp += (kw - 1)*chan1; - if (kw == 7) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; p7 = sp[5*chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; p5 = p7; @@ -928,6 +964,14 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 6) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; @@ -962,6 +1006,14 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 5) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; @@ -996,6 +1048,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; @@ -1030,6 +1088,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 3) { + p2 = sp[0]; p3 = sp[chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; @@ -1064,6 +1128,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 2) { + p2 = sp[0]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; @@ -1098,6 +1168,10 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else /*if (kw == 1)*/ { + k0 = pk[0]; + + sp += (kw - 1)*chan1; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = sp[0]; @@ -1128,6 +1202,8 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } } } + + pk += kw; } } diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_D64nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_D64nw.c index 54e11c64a49..389c1b52c1e 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_D64nw.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_D64nw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,13 +150,14 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, pk = k + off; sp = sl0; - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; - dp = dl; kh = n - off; if (kh == 4) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; + sp += 3*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -184,6 +185,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 3) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + p2 = sp[0]; p3 = sp[sll]; + sp += 2*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -211,6 +216,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 2) { + + k0 = pk[0]; k1 = pk[1]; + p2 = sp[0]; + sp += sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -238,6 +247,9 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else /* if (kh == 1) */ { + + k0 = pk[0]; + for (j = 0; j < hsize; j++) { p0 = sp[0]; @@ -322,17 +334,16 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, if (kw > 2*MAX_KER) kw = MAX_KER; else if (kw > MAX_KER) kw = kw/2; - p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; - sp0 += chan3; - p5 = sp0[0]; p6 = sp0[chan1]; p7 = sp0[chan2]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - dp = dl; if (kw == 7) { + + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; + p5 = sp0[0]; p6 = sp0[chan1]; p7 = sp0[chan2]; sp = sp0 += chan3; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -362,7 +373,13 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else if (kw == 6) { + + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; + p5 = sp0[0]; p6 = sp0[chan1]; sp = sp0 += chan2; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -392,7 +409,13 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else if (kw == 5) { + + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; + p5 = sp0[0]; sp = sp0 += chan1; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -423,7 +446,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; sp = sp0; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -453,7 +479,11 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else if (kw == 3) { + + p2 = sp0[0]; p3 = sp0[chan1]; + sp0 += chan3; sp = sp0 -= chan1; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -483,7 +513,11 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else { /* kw == 2 */ + + p2 = sp0[0]; + sp0 += chan3; sp = sp0 -= chan2; + k0 = pk[0]; k1 = pk[1]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_F32nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_F32nw.c index e87607ddf12..e6c68de5054 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_F32nw.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_F32nw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,13 +150,14 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, pk = k + off; sp = sl0; - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; - dp = dl; kh = n - off; if (kh == 4) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; + sp += 3*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -184,6 +185,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 3) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + p2 = sp[0]; p3 = sp[sll]; + sp += 2*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -211,6 +216,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 2) { + + k0 = pk[0]; k1 = pk[1]; + p2 = sp[0]; + sp += sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -238,6 +247,9 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else /* if (kh == 1) */ { + + k0 = pk[0]; + for (j = 0; j < hsize; j++) { p0 = sp[0]; @@ -322,17 +334,15 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, if (kw > 2*MAX_KER) kw = MAX_KER; else if (kw > MAX_KER) kw = kw/2; - p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; - sp0 += chan3; - p5 = sp0[0]; p6 = sp0[chan1]; p7 = sp0[chan2]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - dp = dl; if (kw == 7) { + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; + p5 = sp0[0]; p6 = sp0[chan1]; p7 = sp0[chan2]; sp = sp0 += chan3; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -362,7 +372,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else if (kw == 6) { + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; + p5 = sp0[0]; p6 = sp0[chan1]; sp = sp0 += chan2; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -392,7 +407,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else if (kw == 5) { + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; + p5 = sp0[0]; sp = sp0 += chan1; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -423,7 +443,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = sp0[0]; p3 = sp0[chan1]; p4 = sp0[chan2]; + sp0 += chan3; sp = sp0; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -453,7 +476,11 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else if (kw == 3) { + + p2 = sp0[0]; p3 = sp0[chan1]; + sp0 += chan3; sp = sp0 -= chan1; + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { @@ -483,7 +510,11 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } else { /* kw == 2 */ + + p2 = sp0[0]; + sp0 += chan3; sp = sp0 -= chan2; + k0 = pk[0]; k1 = pk[1]; if (pk == k) { for (i = 0; i <= (wid - 2); i += 2) { diff --git a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c index 49412c7d7ef..438531e2c07 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConv_u16nw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -286,13 +286,14 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, pk = k + off; sp = sl0; - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; - dp = dl; kh = n - off; if (kh == 4) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + p2 = sp[0]; p3 = sp[sll]; p4 = sp[2*sll]; + sp += 3*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -325,6 +326,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 3) { + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + p2 = sp[0]; p3 = sp[sll]; + sp += 2*sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -357,6 +362,10 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else if (kh == 2) { + + k0 = pk[0]; k1 = pk[1]; + p2 = sp[0]; + sp += sll; for (j = 0; j <= (hsize - 2); j += 2) { @@ -389,6 +398,9 @@ static mlib_status mlib_ImageConv1xN(mlib_image *dst, } } else /* if (kh == 1) */ { + + k0 = pk[0]; + for (j = 0; j < hsize; j++) { p0 = sp[0]; @@ -536,15 +548,14 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, sp = sl; dp = dl; - p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; - p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - pk += kw; - if (kw == 7) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; p7 = buff[5]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; p5 = p7; @@ -583,6 +594,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 6) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; p6 = buff[4]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; @@ -618,6 +635,12 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 5) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + p5 = buff[3]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; @@ -653,6 +676,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = buff[0]; p3 = buff[1]; p4 = buff[2]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; @@ -688,6 +715,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else if (kw == 3) { + p2 = buff[0]; p3 = buff[1]; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; @@ -723,6 +754,10 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } else /*if (kw == 2)*/ { + p2 = buff[0]; + + k0 = pk[0]; k1 = pk[1]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; @@ -756,6 +791,8 @@ mlib_status CONV_FUNC(MxN)(mlib_image *dst, } } } + + pk += kw; } } @@ -882,17 +919,16 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, if (kw > MAX_KER) kw = kw/2; off += kw; - p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; - p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; p7 = sp[5*chan1]; - - k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; - k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; - pk += kw; - - sp += (kw - 1)*chan1; - if (kw == 7) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; p7 = sp[5*chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; k6 = pk[6]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; p5 = p7; @@ -927,6 +963,14 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 6) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; p6 = sp[chan2 + chan2]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; k5 = pk[5]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; p4 = p6; @@ -961,6 +1005,14 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 5) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + p5 = sp[chan2 + chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + k4 = pk[4]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; p3 = p5; @@ -995,6 +1047,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 4) { + p2 = sp[0]; p3 = sp[chan1]; p4 = sp[chan2]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; k3 = pk[3]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; p2 = p4; @@ -1029,6 +1087,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 3) { + p2 = sp[0]; p3 = sp[chan1]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; k2 = pk[2]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; p1 = p3; @@ -1063,6 +1127,12 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else if (kw == 2) { + p2 = sp[0]; + + sp += (kw - 1)*chan1; + + k0 = pk[0]; k1 = pk[1]; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = p2; @@ -1097,6 +1167,10 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } else /*if (kw == 1)*/ { + k0 = pk[0]; + + sp += (kw - 1)*chan1; + if (l < (n - 1) || off < m) { for (i = 0; i <= (wid - 2); i += 2) { p0 = sp[0]; @@ -1127,6 +1201,8 @@ mlib_status CONV_FUNC_I(MxN)(mlib_image *dst, } } } + + pk += kw; } } diff --git a/src/java.desktop/share/native/libmlib_image/mlib_c_ImageConvVersion.c b/src/java.desktop/share/native/libmlib_image/mlib_c_ImageConvVersion.c index 5f8768fb180..b7e685609c9 100644 --- a/src/java.desktop/share/native/libmlib_image/mlib_c_ImageConvVersion.c +++ b/src/java.desktop/share/native/libmlib_image/mlib_c_ImageConvVersion.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ mlib_s32 mlib_ImageConvVersion(mlib_s32 m, mlib_s32 scale, mlib_type type) { - mlib_d64 dscale = 1.0 / (1 << scale); /* 16 < scale <= 31 */ + mlib_d64 dscale = 1.0 / (((mlib_s64)1) << scale); /* 16 < scale <= 31 */ if (type == MLIB_BYTE) { if ((m * n * dscale * 32768.0) > MAX_U8) From 784dd56ce2fbbbf4d94740e1ce0438907e59f575 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 6 Mar 2026 18:02:16 +0000 Subject: [PATCH 097/170] 8378999: BeanContextSupport.add(Object) synchronizes on its argument Reviewed-by: aivanov, serb --- .../beans/beancontext/BeanContextSupport.java | 133 +++++++++--------- 1 file changed, 63 insertions(+), 70 deletions(-) diff --git a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java index 3aa77048f8f..884b36d4b12 100644 --- a/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java +++ b/src/java.desktop/share/classes/java/beans/beancontext/BeanContextSupport.java @@ -422,42 +422,54 @@ public class BeanContextSupport extends BeanContextChildSupport BeanContextChild cbcc = getChildBeanContextChild(targetChild); BeanContextChild bccp = null; - synchronized(targetChild) { + if (targetChild instanceof BeanContextProxy) { + bccp = ((BeanContextProxy)targetChild).getBeanContextProxy(); - if (targetChild instanceof BeanContextProxy) { - bccp = ((BeanContextProxy)targetChild).getBeanContextProxy(); + if (bccp == null) throw new NullPointerException("BeanContextPeer.getBeanContextProxy()"); + } - if (bccp == null) throw new NullPointerException("BeanContextPeer.getBeanContextProxy()"); - } + BCSChild bcsc = createBCSChild(targetChild, bccp); + BCSChild pbcsc = null; - BCSChild bcsc = createBCSChild(targetChild, bccp); - BCSChild pbcsc = null; + synchronized (children) { + children.put(targetChild, bcsc); - synchronized (children) { - children.put(targetChild, bcsc); + if (bccp != null) children.put(bccp, pbcsc = createBCSChild(bccp, targetChild)); + } - if (bccp != null) children.put(bccp, pbcsc = createBCSChild(bccp, targetChild)); - } + if (cbcc != null) synchronized(cbcc) { + try { + cbcc.setBeanContext(getBeanContextPeer()); + } catch (PropertyVetoException pve) { - if (cbcc != null) synchronized(cbcc) { - try { - cbcc.setBeanContext(getBeanContextPeer()); - } catch (PropertyVetoException pve) { + synchronized (children) { + children.remove(targetChild); - synchronized (children) { - children.remove(targetChild); - - if (bccp != null) children.remove(bccp); - } - - throw new IllegalStateException(); + if (bccp != null) children.remove(bccp); } - cbcc.addPropertyChangeListener("beanContext", childPCL); - cbcc.addVetoableChangeListener("beanContext", childVCL); + throw new IllegalStateException(); } - Visibility v = getChildVisibility(targetChild); + cbcc.addPropertyChangeListener("beanContext", childPCL); + cbcc.addVetoableChangeListener("beanContext", childVCL); + } + + Visibility v = getChildVisibility(targetChild); + + if (v != null) { + if (okToUseGui) + v.okToUseGui(); + else + v.dontUseGui(); + } + + if (getChildSerializable(targetChild) != null) serializable++; + + childJustAddedHook(targetChild, bcsc); + + if (bccp != null) { + v = getChildVisibility(bccp); if (v != null) { if (okToUseGui) @@ -466,26 +478,9 @@ public class BeanContextSupport extends BeanContextChildSupport v.dontUseGui(); } - if (getChildSerializable(targetChild) != null) serializable++; - - childJustAddedHook(targetChild, bcsc); - - if (bccp != null) { - v = getChildVisibility(bccp); - - if (v != null) { - if (okToUseGui) - v.okToUseGui(); - else - v.dontUseGui(); - } - - if (getChildSerializable(bccp) != null) serializable++; - - childJustAddedHook(bccp, pbcsc); - } - + if (getChildSerializable(bccp) != null) serializable++; + childJustAddedHook(bccp, pbcsc); } // The specification requires that we fire a notification of the change @@ -536,42 +531,40 @@ public class BeanContextSupport extends BeanContextChildSupport // we are required to notify the child that it is no longer nested here if // it implements java.beans.beancontext.BeanContextChild - synchronized(targetChild) { - if (callChildSetBC) { - BeanContextChild cbcc = getChildBeanContextChild(targetChild); - if (cbcc != null) synchronized(cbcc) { - cbcc.removePropertyChangeListener("beanContext", childPCL); - cbcc.removeVetoableChangeListener("beanContext", childVCL); - - try { - cbcc.setBeanContext(null); - } catch (PropertyVetoException pve1) { - cbcc.addPropertyChangeListener("beanContext", childPCL); - cbcc.addVetoableChangeListener("beanContext", childVCL); - throw new IllegalStateException(); - } + if (callChildSetBC) { + BeanContextChild cbcc = getChildBeanContextChild(targetChild); + if (cbcc != null) synchronized(cbcc) { + cbcc.removePropertyChangeListener("beanContext", childPCL); + cbcc.removeVetoableChangeListener("beanContext", childVCL); + try { + cbcc.setBeanContext(null); + } catch (PropertyVetoException pve1) { + cbcc.addPropertyChangeListener("beanContext", childPCL); + cbcc.addVetoableChangeListener("beanContext", childVCL); + throw new IllegalStateException(); } + } + } - synchronized (children) { - children.remove(targetChild); + synchronized (children) { + children.remove(targetChild); - if (bcsc.isProxyPeer()) { - pbcsc = children.get(peer = bcsc.getProxyPeer()); - children.remove(peer); - } + if (bcsc.isProxyPeer()) { + pbcsc = children.get(peer = bcsc.getProxyPeer()); + children.remove(peer); } + } - if (getChildSerializable(targetChild) != null) serializable--; + if (getChildSerializable(targetChild) != null) serializable--; - childJustRemovedHook(targetChild, bcsc); + childJustRemovedHook(targetChild, bcsc); - if (peer != null) { - if (getChildSerializable(peer) != null) serializable--; + if (peer != null) { + if (getChildSerializable(peer) != null) serializable--; - childJustRemovedHook(peer, pbcsc); - } + childJustRemovedHook(peer, pbcsc); } fireChildrenRemoved(new BeanContextMembershipEvent(getBeanContextPeer(), peer == null ? new Object[] { targetChild } : new Object[] { targetChild, peer } )); From 8ef39a22d855d1b1aaeb39549f6e8413f362338b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Sat, 7 Mar 2026 10:56:00 +0000 Subject: [PATCH 098/170] 8374490: Test jdk/jfr/event/runtime/TestSafepointEvents.java failed: Expected event 'jdk.SafepointStateSynchronization' to be present Reviewed-by: egahlin --- .../event/runtime/TestSafepointEvents.java | 51 +++++++------------ 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java b/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java index 0dccbc4495a..022a9c27674 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java +++ b/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ package jdk.jfr.event.runtime; import static jdk.test.lib.Asserts.assertTrue; +import static jdk.test.lib.Asserts.assertEquals; import java.nio.file.Paths; import java.time.Duration; @@ -31,7 +32,6 @@ import java.util.*; import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; -import jdk.test.lib.Asserts; import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; import jdk.test.whitebox.WhiteBox; @@ -65,43 +65,30 @@ public class TestSafepointEvents { recording.stop(); try { - // Verify that each event type was seen at least once - List events = Events.fromRecording(recording); - for (String name : EVENT_NAMES) { - boolean found = false; - for (RecordedEvent event : events) { - found = event.getEventType().getName().equals(name); - if (found) { - break; - } - } - assertTrue(found, "Expected event from test [" + name + "]"); - } - // Collect all events grouped by safepoint id SortedMap> safepointIds = new TreeMap<>(); - for (RecordedEvent event : events) { + for (RecordedEvent event : Events.fromRecording(recording)) { Long safepointId = event.getValue("safepointId"); - if (!safepointIds.containsKey(safepointId)) { - safepointIds.put(safepointId, new HashSet<>()); - } - safepointIds.get(safepointId).add(event.getEventType().getName()); + String eventName = event.getEventType().getName(); + safepointIds.computeIfAbsent(safepointId, k -> new HashSet<>()).add(eventName); } - // The last safepoint may be related to stopping the recording and can thus be - // incomplete - so if there is more than one, ignore the last one - if (safepointIds.size() > 1) { - safepointIds.remove(safepointIds.lastKey()); - } - Asserts.assertGreaterThanOrEqual(safepointIds.size(), 1, "At least 1 safepoint must have occured"); - - // Verify that each safepoint id has an occurence of every event type, - // this ensures that all events related to a given safepoint had the same id - for (Set safepointEvents : safepointIds.values()) { - for (String name : EVENT_NAMES) { - assertTrue(safepointEvents.contains(name), "Expected event '" + name + "' to be present"); + // Select the first set that is complete. + Set safepointEvents = null; + for (Long key : safepointIds.keySet()) { + safepointEvents = safepointIds.get(key); + if (safepointEvents.size() == EVENT_NAMES.length) { + break; } } + assertEquals(safepointEvents.size(), EVENT_NAMES.length, + "At least one safepoint id should map to a set containing an instance of each enabled event type."); + + // Verify that the selected set contains an instance of each enabled event type. + for (String name : EVENT_NAMES) { + assertTrue(safepointEvents.contains(name), "Expected event '" + name + "' to be present"); + } + } catch (Throwable e) { recording.dump(Paths.get("failed.jfr")); throw e; From 7e5acdc6fa0ca3993bc47bdbb90dc18eebea27b7 Mon Sep 17 00:00:00 2001 From: Jeremy Wood Date: Sun, 8 Mar 2026 00:39:15 +0000 Subject: [PATCH 099/170] 8378057: CAccessibility roleKey and AWTAccessor.AccessibleBundleAccessor are Redundant Reviewed-by: kizune, serb --- .../classes/sun/lwawt/macosx/CAccessibility.java | 12 +++++++----- .../libawt_lwawt/awt/JavaAccessibilityUtilities.m | 14 -------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java index 494995735e6..636d8240a55 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java @@ -116,7 +116,9 @@ final class CAccessibility implements PropertyChangeListener { if (newValue instanceof Accessible) { AccessibleContext nvAC = ((Accessible) newValue).getAccessibleContext(); AccessibleRole nvRole = nvAC.getAccessibleRole(); - if (!ignoredRoles.contains(roleKey(nvRole))) { + String roleStr = nvRole == null ? null : + AWTAccessor.getAccessibleBundleAccessor().getKey(nvRole); + if (!ignoredRoles.contains(roleStr)) { focusChanged(); } } @@ -1034,8 +1036,10 @@ final class CAccessibility implements PropertyChangeListener { // "ignored", and we should skip it and its descendants if (isShowing(context)) { final AccessibleRole role = context.getAccessibleRole(); - if (role != null && ignoredRoles != null && - ignoredRoles.contains(roleKey(role))) { + String roleStr = role == null ? null : + AWTAccessor.getAccessibleBundleAccessor().getKey(role); + if (roleStr != null && ignoredRoles != null && + ignoredRoles.contains(roleStr)) { // Get the child's unignored children. _addChildren(child, whichChildren, false, childrenAndRoles, ChildrenOperations.COMMON); @@ -1096,8 +1100,6 @@ final class CAccessibility implements PropertyChangeListener { return isShowing(parentContext); } - private static native String roleKey(AccessibleRole aRole); - public static Object[] getChildren(final Accessible a, final Component c) { if (a == null) return null; return invokeAndWait(new Callable() { diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m index bf66df162d1..fcd330940cc 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m @@ -325,20 +325,6 @@ static BOOL JavaAccessibilityIsSupportedAttribute(id element, NSString *attribut return [[element accessibilityAttributeNames] indexOfObject:attribute] != NSNotFound; } -/* - * Class: sun_lwawt_macosx_CAccessibility - * Method: roleKey - * Signature: (Ljavax/accessibility/AccessibleRole;)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_sun_lwawt_macosx_CAccessibility_roleKey -(JNIEnv *env, jclass clz, jobject axRole) -{ - DECLARE_CLASS_RETURN(sjc_AccessibleRole, "javax/accessibility/AccessibleRole", NULL); - DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", NULL); - return (*env)->GetObjectField(env, axRole, sjf_key); -} - - // errors from NSAccessibilityErrors void JavaAccessibilityRaiseSetAttributeToIllegalTypeException(const char *functionName, id element, NSString *attribute, id value) { From b159addb80701eed6bc548accb6bee1f535b8e58 Mon Sep 17 00:00:00 2001 From: Kerem Kat Date: Sun, 8 Mar 2026 03:12:02 +0000 Subject: [PATCH 100/170] 8379231: Assembler::mov64 always emits 10-byte movabs even for small immediates Reviewed-by: qamai, dlong --- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 24 ++++++++++++++-------- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 3 +++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index b54f6adc263..2d46a50d426 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -961,7 +961,7 @@ void MacroAssembler::call(AddressLiteral entry, Register rscratch) { void MacroAssembler::ic_call(address entry, jint method_index) { RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index); // Needs full 64-bit immediate for later patching. - mov64(rax, (int64_t)Universe::non_oop_word()); + Assembler::mov64(rax, (int64_t)Universe::non_oop_word()); call(AddressLiteral(entry, rh)); } @@ -1961,6 +1961,20 @@ void MacroAssembler::movflt(XMMRegister dst, AddressLiteral src, Register rscrat } } +void MacroAssembler::mov64(Register dst, int64_t imm64) { + if (is_uimm32(imm64)) { + movl(dst, checked_cast(imm64)); + } else if (is_simm32(imm64)) { + movq(dst, checked_cast(imm64)); + } else { + Assembler::mov64(dst, imm64); + } +} + +void MacroAssembler::mov64(Register dst, int64_t imm64, relocInfo::relocType rtype, int format) { + Assembler::mov64(dst, imm64, rtype, format); +} + void MacroAssembler::movptr(Register dst, Register src) { movq(dst, src); } @@ -1971,13 +1985,7 @@ void MacroAssembler::movptr(Register dst, Address src) { // src should NEVER be a real pointer. Use AddressLiteral for true pointers void MacroAssembler::movptr(Register dst, intptr_t src) { - if (is_uimm32(src)) { - movl(dst, checked_cast(src)); - } else if (is_simm32(src)) { - movq(dst, checked_cast(src)); - } else { - mov64(dst, src); - } + mov64(dst, src); } void MacroAssembler::movptr(Address dst, Register src) { diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 5c049f710e2..8469deaa8be 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1869,6 +1869,9 @@ public: void mov_metadata(Register dst, Metadata* obj); void mov_metadata(Address dst, Metadata* obj, Register rscratch); + void mov64(Register dst, int64_t imm64); + void mov64(Register dst, int64_t imm64, relocInfo::relocType rtype, int format); + void movptr(Register dst, Register src); void movptr(Register dst, Address src); void movptr(Register dst, AddressLiteral src); From 8c4c8a16171187a4a1e9a95c04d20f2efd94145f Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 9 Mar 2026 01:21:34 +0000 Subject: [PATCH 101/170] 8378417: Printing All pages results in NPE for 1.1 PrintJob Reviewed-by: prr, aivanov --- .../classes/sun/print/PrintJobDelegate.java | 8 ++- .../classes/sun/awt/windows/WPrinterJob.java | 4 +- .../awt/PrintJob/TestPrintNoException.java | 61 +++++++++++++++++++ .../java/awt/print/PrinterJob/PageRanges.java | 2 +- 4 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 test/jdk/java/awt/PrintJob/TestPrintNoException.java diff --git a/src/java.desktop/share/classes/sun/print/PrintJobDelegate.java b/src/java.desktop/share/classes/sun/print/PrintJobDelegate.java index 5a88d4b9d45..bca3301b5c9 100644 --- a/src/java.desktop/share/classes/sun/print/PrintJobDelegate.java +++ b/src/java.desktop/share/classes/sun/print/PrintJobDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -526,8 +526,10 @@ public class PrintJobDelegate implements Printable, Runnable { } PageRanges range = (PageRanges)attributes.get(PageRanges.class); - int[][] members = range.getMembers(); - jobAttributes.setPageRanges(members); + if (range != null) { + int[][] members = range.getMembers(); + jobAttributes.setPageRanges(members); + } SheetCollate collation = (SheetCollate)attributes.get(SheetCollate.class); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java b/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java index 1da9db3a35b..b238921cb77 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java @@ -1734,7 +1734,9 @@ public final class WPrinterJob extends RasterPrinterJob attributes.add(new PageRanges(from, to)); setPageRange(from, to); } else { - attributes.remove(PageRanges.class); + // Sets default values for PageRange attribute and setPageRange + attributes.add(new PageRanges(1, + Integer.MAX_VALUE)); setPageRange(Pageable.UNKNOWN_NUMBER_OF_PAGES, Pageable.UNKNOWN_NUMBER_OF_PAGES); } diff --git a/test/jdk/java/awt/PrintJob/TestPrintNoException.java b/test/jdk/java/awt/PrintJob/TestPrintNoException.java new file mode 100644 index 00000000000..b54ac8de56b --- /dev/null +++ b/test/jdk/java/awt/PrintJob/TestPrintNoException.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Frame; +import java.awt.JobAttributes; +import java.awt.PrintJob; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.KeyEvent; + +/* + * @test + * @bug 8378417 + * @key headful printer + * @summary Verifies No Exception is thrown when Printing "All" pages + * @run main TestPrintNoException + */ + +public class TestPrintNoException { + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + Thread t = new Thread (() -> { + robot.delay(5000); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + }); + + Frame testFrame = new Frame("print"); + try { + t.start(); + PrintJob pj = Toolkit.getDefaultToolkit().getPrintJob(testFrame, null, null); + if (pj != null) { + pj.end(); + } + } finally { + testFrame.dispose(); + } + } +} diff --git a/test/jdk/java/awt/print/PrinterJob/PageRanges.java b/test/jdk/java/awt/print/PrinterJob/PageRanges.java index 691357d5a3c..3a84725910c 100644 --- a/test/jdk/java/awt/print/PrinterJob/PageRanges.java +++ b/test/jdk/java/awt/print/PrinterJob/PageRanges.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6575331 8297191 8373239 + * @bug 6575331 8297191 8373239 8378417 * @key printer * @summary The specified pages should be printed. * @library /java/awt/regtesthelpers From b2728d0a4b1185efac73d18ee3ac3f928f6a0b42 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Mon, 9 Mar 2026 07:26:02 +0000 Subject: [PATCH 102/170] 8376891: [VectorAlgorithms] add more if-conversion benchmarks and tests Reviewed-by: qamai, psandoz, xgong, jbhateja --- .../vectorization/TestVectorAlgorithms.java | 135 +++++++- .../vectorization/VectorAlgorithmsImpl.java | 325 ++++++++++++++++- .../bench/vm/compiler/VectorAlgorithms.java | 74 +++- .../vm/compiler/VectorAlgorithmsImpl.java | 326 +++++++++++++++++- 4 files changed, 815 insertions(+), 45 deletions(-) diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java index 785a6de30a0..ed04950eb07 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java @@ -79,6 +79,12 @@ public class TestVectorAlgorithms { VectorAlgorithmsImpl.Data d; + // We should test with a wide range of probabilities, to ensure correctness, + // and also to ensure we get all branches compiled, so IR matching compiles + // also for branches that require a very extreme probability. + private static final float[] BRANCH_PROBABILITIES = new float[] {0f, 0.1f, 0.3f, 0.5f, 0.7f, 0.9f, 1f}; + private static int branch_probabilities_idx = 0; + public static void main(String[] args) { TestFramework framework = new TestFramework(); framework.addFlags("--add-modules=jdk.incubator.vector", @@ -133,16 +139,19 @@ public class TestVectorAlgorithms { testGroups.get("findMinIndexI").put("findMinIndexI_VectorAPI", i -> { return findMinIndexI_VectorAPI(d.aI); }); testGroups.put("findI", new HashMap()); - testGroups.get("findI").put("findI_loop", i -> { return findI_loop(d.aI, d.eI[i]); }); - testGroups.get("findI").put("findI_VectorAPI", i -> { return findI_VectorAPI(d.aI, d.eI[i]); }); + testGroups.get("findI").put("findI_loop", i -> { return findI_loop(d.aI, d.eI_findI[i]); }); + testGroups.get("findI").put("findI_VectorAPI", i -> { return findI_VectorAPI(d.aI, d.eI_findI[i]); }); testGroups.put("reverseI", new HashMap()); testGroups.get("reverseI").put("reverseI_loop", i -> { return reverseI_loop(d.aI, d.rI1); }); testGroups.get("reverseI").put("reverseI_VectorAPI", i -> { return reverseI_VectorAPI(d.aI, d.rI2); }); testGroups.put("filterI", new HashMap()); - testGroups.get("filterI").put("filterI_loop", i -> { return filterI_loop(d.aI, d.rI1, d.eI[i]); }); - testGroups.get("filterI").put("filterI_VectorAPI", i -> { return filterI_VectorAPI(d.aI, d.rI2, d.eI[i]); }); + testGroups.get("filterI").put("filterI_loop", i -> { return filterI_loop(d.aI_filterI, d.rI1, d.eI_filterI); }); + testGroups.get("filterI").put("filterI_VectorAPI_v1", i -> { return filterI_VectorAPI_v1(d.aI_filterI, d.rI2, d.eI_filterI); }); + testGroups.get("filterI").put("filterI_VectorAPI_v2_l2", i -> { return filterI_VectorAPI_v2_l2(d.aI_filterI, d.rI3, d.eI_filterI); }); + testGroups.get("filterI").put("filterI_VectorAPI_v2_l4", i -> { return filterI_VectorAPI_v2_l4(d.aI_filterI, d.rI4, d.eI_filterI); }); + testGroups.get("filterI").put("filterI_VectorAPI_v2_l8", i -> { return filterI_VectorAPI_v2_l8(d.aI_filterI, d.rI5, d.eI_filterI); }); testGroups.put("reduceAddIFieldsX4", new HashMap()); testGroups.get("reduceAddIFieldsX4").put("reduceAddIFieldsX4_loop", i -> { return reduceAddIFieldsX4_loop(d.oopsX4, d.memX4); }); @@ -152,6 +161,17 @@ public class TestVectorAlgorithms { testGroups.get("lowerCaseB").put("lowerCaseB_loop", i -> { return lowerCaseB_loop(d.strB, d.rB1); }); testGroups.get("lowerCaseB").put("lowerCaseB_VectorAPI_v1", i -> { return lowerCaseB_VectorAPI_v1(d.strB, d.rB2); }); testGroups.get("lowerCaseB").put("lowerCaseB_VectorAPI_v2", i -> { return lowerCaseB_VectorAPI_v2(d.strB, d.rB3); }); + + testGroups.put("conditionalSumB", new HashMap()); + testGroups.get("conditionalSumB").put("conditionalSumB_loop", i -> { return conditionalSumB_loop(d.strB); }); + testGroups.get("conditionalSumB").put("conditionalSumB_VectorAPI_v1", i -> { return conditionalSumB_VectorAPI_v1(d.strB); }); + testGroups.get("conditionalSumB").put("conditionalSumB_VectorAPI_v2", i -> { return conditionalSumB_VectorAPI_v2(d.strB); }); + + + testGroups.put("pieceWise2FunctionF", new HashMap()); + testGroups.get("pieceWise2FunctionF").put("pieceWise2FunctionF_loop", _ -> { return pieceWise2FunctionF_loop(d.xF, d.rF1); }); + testGroups.get("pieceWise2FunctionF").put("pieceWise2FunctionF_VectorAPI_v1", _ -> { return pieceWise2FunctionF_VectorAPI_v1(d.xF, d.rF2); }); + testGroups.get("pieceWise2FunctionF").put("pieceWise2FunctionF_VectorAPI_v2", _ -> { return pieceWise2FunctionF_VectorAPI_v2(d.xF, d.rF3); }); } @Warmup(100) @@ -186,12 +206,21 @@ public class TestVectorAlgorithms { "reverseI_loop", "reverseI_VectorAPI", "filterI_loop", - "filterI_VectorAPI", + "filterI_VectorAPI_v1", + "filterI_VectorAPI_v2_l2", + "filterI_VectorAPI_v2_l4", + "filterI_VectorAPI_v2_l8", "reduceAddIFieldsX4_loop", "reduceAddIFieldsX4_VectorAPI", "lowerCaseB_loop", "lowerCaseB_VectorAPI_v1", - "lowerCaseB_VectorAPI_v2"}) + "lowerCaseB_VectorAPI_v2", + "conditionalSumB_loop", + "conditionalSumB_VectorAPI_v1", + "conditionalSumB_VectorAPI_v2", + "pieceWise2FunctionF_loop", + "pieceWise2FunctionF_VectorAPI_v1", + "pieceWise2FunctionF_VectorAPI_v2"}) public void runTests(RunInfo info) { // Repeat many times, so that we also have multiple iterations for post-warmup to potentially recompile int iters = info.isWarmUp() ? 1 : 20; @@ -200,7 +229,9 @@ public class TestVectorAlgorithms { int size = 100_000 + RANDOM.nextInt(10_000); int seed = RANDOM.nextInt(); int numXObjects = 10_000; - d = new VectorAlgorithmsImpl.Data(size, seed, numXObjects); + branch_probabilities_idx = (branch_probabilities_idx + 1) % BRANCH_PROBABILITIES.length; + float branchProbability = BRANCH_PROBABILITIES[branch_probabilities_idx]; + d = new VectorAlgorithmsImpl.Data(size, seed, numXObjects, branchProbability); // Run all tests for (Map.Entry> group_entry : testGroups.entrySet()) { @@ -510,8 +541,45 @@ public class TestVectorAlgorithms { IRNode.COMPRESS_VI, "> 0", IRNode.STORE_VECTOR_MASKED, "> 0"}, applyIfCPUFeatureOr = {"avx2", "true", "sve", "true"}) - public Object filterI_VectorAPI(int[] a, int[] r, int threshold) { - return VectorAlgorithmsImpl.filterI_VectorAPI(a, r, threshold); + public Object filterI_VectorAPI_v1(int[] a, int[] r, int threshold) { + return VectorAlgorithmsImpl.filterI_VectorAPI_v1(a, r, threshold); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "> 0", + IRNode.VECTOR_MASK_CMP, "= 0", // not implemented + IRNode.VECTOR_TEST, "= 0", // not implemented + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeature = {"sse4.1", "true"}) + // x86 seems to have a limitation with 2-element VectorStoreMask, this blocks intrinsification + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_2, "> 0", + IRNode.VECTOR_MASK_CMP, "> 0", + IRNode.VECTOR_TEST, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"asimd", "true"}) + public Object filterI_VectorAPI_v2_l2(int[] a, int[] r, int threshold) { + return VectorAlgorithmsImpl.filterI_VectorAPI_v2_l2(a, r, threshold); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.VECTOR_MASK_CMP, "> 0", + IRNode.VECTOR_TEST, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + public Object filterI_VectorAPI_v2_l4(int[] a, int[] r, int threshold) { + return VectorAlgorithmsImpl.filterI_VectorAPI_v2_l4(a, r, threshold); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_8, "> 0", + IRNode.VECTOR_MASK_CMP, "> 0", + IRNode.VECTOR_TEST, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"avx2", "true"}) + // Note: need 8int = 256bit vector. NEON only has 128bit. + public Object filterI_VectorAPI_v2_l8(int[] a, int[] r, int threshold) { + return VectorAlgorithmsImpl.filterI_VectorAPI_v2_l8(a, r, threshold); } @Test @@ -559,4 +627,53 @@ public class TestVectorAlgorithms { public Object lowerCaseB_VectorAPI_v2(byte[] a, byte[] r) { return VectorAlgorithmsImpl.lowerCaseB_VectorAPI_v2(a, r); } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0"}) + // Currently does not vectorize, but might in the future. + public Object conditionalSumB_loop(byte[] a) { + return VectorAlgorithmsImpl.conditionalSumB_loop(a); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE + "min(max_int, max_byte)", "> 0", + IRNode.ADD_VI, IRNode.VECTOR_SIZE + "min(max_int, max_byte)", "> 0"}, + applyIfCPUFeature = {"avx2", "true"}) + // Note: we need at least a 256bit int vector. NEON only has 128bit. + public Object conditionalSumB_VectorAPI_v1(byte[] a) { + return VectorAlgorithmsImpl.conditionalSumB_VectorAPI_v1(a); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.ADD_VI, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + public Object conditionalSumB_VectorAPI_v2(byte[] a) { + return VectorAlgorithmsImpl.conditionalSumB_VectorAPI_v2(a); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_F, "= 0"}) + // Currently does not vectorize, but might in the future. + public Object pieceWise2FunctionF_loop(float[] a, float[] r) { + return VectorAlgorithmsImpl.pieceWise2FunctionF_loop(a, r); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", + IRNode.MUL_VF, "> 0", + IRNode.SQRT_VF, "> 0"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + public Object pieceWise2FunctionF_VectorAPI_v1(float[] a, float[] r) { + return VectorAlgorithmsImpl.pieceWise2FunctionF_VectorAPI_v1(a, r); + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", + IRNode.MUL_VF, "> 0", + IRNode.SQRT_VF, "> 0"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + public Object pieceWise2FunctionF_VectorAPI_v2(float[] a, float[] r) { + return VectorAlgorithmsImpl.pieceWise2FunctionF_VectorAPI_v2(a, r); + } } diff --git a/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java b/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java index 2dfac704069..8276d90509f 100644 --- a/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java +++ b/test/hotspot/jtreg/compiler/vectorization/VectorAlgorithmsImpl.java @@ -36,6 +36,8 @@ public class VectorAlgorithmsImpl { private static final VectorSpecies SPECIES_I = IntVector.SPECIES_PREFERRED; private static final VectorSpecies SPECIES_I512 = IntVector.SPECIES_512; private static final VectorSpecies SPECIES_I256 = IntVector.SPECIES_256; + private static final VectorSpecies SPECIES_I128 = IntVector.SPECIES_128; + private static final VectorSpecies SPECIES_I64 = IntVector.SPECIES_64; private static final VectorSpecies SPECIES_B = ByteVector.SPECIES_PREFERRED; private static final VectorSpecies SPECIES_B64 = ByteVector.SPECIES_64; private static final VectorSpecies SPECIES_F = FloatVector.SPECIES_PREFERRED; @@ -58,15 +60,31 @@ public class VectorAlgorithmsImpl { public int[] rI2; public int[] rI3; public int[] rI4; - public int[] eI; + public int[] rI5; + + // Search element for "findI" + public int[] eI_findI; // The test has to use the same index into eI for all implementations. But in the // benchmark, we'd like to use random indices, so we use the index to advance through // the array. - public int eI_idx = 0; + public int eI_findI_idx = 0; + + // Data and threshold eI value for "filterI". + // We create the data in a range, and then pick a threshold scaled to that range, + // so that the branch in the filter is branchProbability. + public int[] aI_filterI; + public int eI_filterI; public float[] aF; public float[] bF; + // Input for piece-wise functions. + // Uniform [0..1[ with probability p and Uniform [1..2[ with probability (1-p) + public float[] xF; + public float[] rF1; + public float[] rF2; + public float[] rF3; + public byte[] aB; public byte[] strB; public byte[] rB1; @@ -76,7 +94,7 @@ public class VectorAlgorithmsImpl { public int[] oopsX4; public int[] memX4; - public Data(int size, int seed, int numX4Objects) { + public Data(int size, int seed, int numX4Objects, float branchProbability) { Random random = new Random(seed); // int: one input array and multiple output arrays so different implementations can @@ -86,14 +104,20 @@ public class VectorAlgorithmsImpl { rI2 = new int[size]; rI3 = new int[size]; rI4 = new int[size]; + rI5 = new int[size]; Arrays.setAll(aI, i -> random.nextInt()); // Populate with some random values from aI, and some totally random values. - eI = new int[0x10000]; - for (int i = 0; i < eI.length; i++) { - eI[i] = (random.nextInt(10) == 0) ? random.nextInt() : aI[random.nextInt(size)]; + eI_findI = new int[0x10000]; + for (int i = 0; i < eI_findI.length; i++) { + eI_findI[i] = (random.nextInt(10) == 0) ? random.nextInt() : aI[random.nextInt(size)]; } + int filterI_range = 1000_000; + aI_filterI = new int[size]; + Arrays.setAll(aI_filterI, i -> random.nextInt(filterI_range)); + eI_filterI = (int)(filterI_range * (1.0f - branchProbability)); + // X4 oop setup. // oopsX4 holds "addresses" (i.e. indices), that point to the 16-byte objects in memX4. oopsX4 = new int[size]; @@ -117,14 +141,30 @@ public class VectorAlgorithmsImpl { bF[i] = random.nextInt(32) - 16; } + xF = new float[size]; + rF1 = new float[size]; + rF2 = new float[size]; + rF3 = new float[size]; + for (int i = 0; i < size; i++) { + xF[i] = (random.nextFloat() < branchProbability) + ? 0f + random.nextFloat() + : 1f + random.nextFloat(); + } + // byte: just random data. aB = new byte[size]; - strB = new byte[size]; rB1 = new byte[size]; rB2 = new byte[size]; rB3 = new byte[size]; random.nextBytes(aB); - random.nextBytes(strB); // TODO: special data! + + // byte string: for lowerCase benchmark. + strB = new byte[size]; + for (int i = 0; i < size; i++) { + strB[i] = (random.nextFloat() < branchProbability) + ? (byte)(random.nextInt(16) + 'A') + : (byte)(random.nextInt(16) + 'a'); + } } } @@ -651,13 +691,12 @@ public class VectorAlgorithmsImpl { return r; } - public static Object filterI_VectorAPI(int[] a, int[] r, int threshold) { - var thresholds = IntVector.broadcast(SPECIES_I, threshold); + public static Object filterI_VectorAPI_v1(int[] a, int[] r, int threshold) { int j = 0; int i = 0; for (; i < SPECIES_I.loopBound(a.length); i += SPECIES_I.length()) { IntVector v = IntVector.fromArray(SPECIES_I, a, i); - var mask = v.compare(VectorOperators.GE, thresholds); + var mask = v.compare(VectorOperators.GE, threshold); v = v.compress(mask); int trueCount = mask.trueCount(); var prefixMask = mask.compress(); @@ -676,6 +715,98 @@ public class VectorAlgorithmsImpl { return r; } + // Idea: on platforms that do not support the "v1" solution with "compress" and + // masked stores, we struggle to deal with the loop-carried dependency of j. + // But we can still use dynamic uniformity to enable some vectorized performance. + public static Object filterI_VectorAPI_v2_l2(int[] a, int[] r, int threshold) { + int j = 0; + int i = 0; + for (; i < SPECIES_I64.loopBound(a.length); i += SPECIES_I64.length()) { + IntVector v = IntVector.fromArray(SPECIES_I64, a, i); + var mask = v.compare(VectorOperators.GE, threshold); + if (mask.allTrue()) { + v.intoArray(r, j); + j += 2; + } else if (mask.anyTrue()) { + if (mask.laneIsSet(0)) { r[j++] = v.lane(0); } + if (mask.laneIsSet(1)) { r[j++] = v.lane(1); } + } else { + // nothing + } + } + for (; i < a.length; i++) { + int ai = a[i]; + if (ai >= threshold) { + r[j++] = ai; + } + } + // Just force the resulting length onto the same array. + r[r.length - 1] = j; + return r; + } + + public static Object filterI_VectorAPI_v2_l4(int[] a, int[] r, int threshold) { + int j = 0; + int i = 0; + for (; i < SPECIES_I128.loopBound(a.length); i += SPECIES_I128.length()) { + IntVector v = IntVector.fromArray(SPECIES_I128, a, i); + var mask = v.compare(VectorOperators.GE, threshold); + if (mask.allTrue()) { + v.intoArray(r, j); + j += 4; + } else if (mask.anyTrue()) { + if (mask.laneIsSet(0)) { r[j++] = v.lane(0); } + if (mask.laneIsSet(1)) { r[j++] = v.lane(1); } + if (mask.laneIsSet(2)) { r[j++] = v.lane(2); } + if (mask.laneIsSet(3)) { r[j++] = v.lane(3); } + } else { + // nothing + } + } + for (; i < a.length; i++) { + int ai = a[i]; + if (ai >= threshold) { + r[j++] = ai; + } + } + // Just force the resulting length onto the same array. + r[r.length - 1] = j; + return r; + } + + public static Object filterI_VectorAPI_v2_l8(int[] a, int[] r, int threshold) { + int j = 0; + int i = 0; + for (; i < SPECIES_I256.loopBound(a.length); i += SPECIES_I256.length()) { + IntVector v = IntVector.fromArray(SPECIES_I256, a, i); + var mask = v.compare(VectorOperators.GE, threshold); + if (mask.allTrue()) { + v.intoArray(r, j); + j += 8; + } else if (mask.anyTrue()) { + if (mask.laneIsSet(0)) { r[j++] = v.lane(0); } + if (mask.laneIsSet(1)) { r[j++] = v.lane(1); } + if (mask.laneIsSet(2)) { r[j++] = v.lane(2); } + if (mask.laneIsSet(3)) { r[j++] = v.lane(3); } + if (mask.laneIsSet(4)) { r[j++] = v.lane(4); } + if (mask.laneIsSet(5)) { r[j++] = v.lane(5); } + if (mask.laneIsSet(6)) { r[j++] = v.lane(6); } + if (mask.laneIsSet(7)) { r[j++] = v.lane(7); } + } else { + // nothing + } + } + for (; i < a.length; i++) { + int ai = a[i]; + if (ai >= threshold) { + r[j++] = ai; + } + } + // Just force the resulting length onto the same array. + r[r.length - 1] = j; + return r; + } + // X4: ints simulate 4-byte oops. // oops: if non-zero (= non-null), every entry simulates a 4-byte oop, pointing into mem. // mem: an int array that simulates the memory. @@ -771,4 +902,176 @@ public class VectorAlgorithmsImpl { } return r; } + + public static int conditionalSumB_loop(byte[] a) { + int sum = 0; + for (int i = 0; i < a.length; i++) { + byte c = a[i]; + if (c >= 'A' && c <= 'Z') { + sum += c; + } + } + return sum; + } + + public static int conditionalSumB_VectorAPI_v1(byte[] a) { + return ConditionalSumB_VectorAPI_V1.compute(a); + } + + private static class ConditionalSumB_VectorAPI_V1 { + // Pick I species to be a full vector, and the B vector a quarter its bit length. + // However, we have to get at least 64bits for the B vector, so at least 256bits + // for the int vector - a sad restriction by the currently very narrow range of + // supported shapes. + private static final int BITS_I = Math.max(256, IntVector.SPECIES_PREFERRED.vectorBitSize()); + private static final int BITS_B = BITS_I / 4; + private static final VectorShape SHAPE_I = VectorShape.forBitSize(BITS_I); + private static final VectorShape SHAPE_B = VectorShape.forBitSize(BITS_B); + private static final VectorSpecies SPECIES_I = SHAPE_I.withLanes(int.class); + private static final VectorSpecies SPECIES_B = SHAPE_B.withLanes(byte.class); + + public static int compute(byte[] a) { + var zeroB = ByteVector.zero(SPECIES_B); + var accI = IntVector.zero(SPECIES_I); + int i; + for (i = 0; i < SPECIES_B.loopBound(a.length); i += SPECIES_B.length()) { + var vB = ByteVector.fromArray(SPECIES_B, a, i); + var maskA = vB.compare(VectorOperators.GE, (byte)'A'); + var maskZ = vB.compare(VectorOperators.LE, (byte)'Z'); + var mask = maskA.and(maskZ); + vB = zeroB.blend(vB, mask); + var vI = vB.castShape(SPECIES_I, 0); + accI = accI.add(vI); + } + int sum = accI.reduceLanes(VectorOperators.ADD); + for (; i < a.length; i++) { + byte c = a[i]; + if (c >= 'A' && c <= 'Z') { + sum += c; + } + } + return sum; + } + } + + public static int conditionalSumB_VectorAPI_v2(byte[] a) { + return ConditionalSumB_VectorAPI_V2.compute(a); + } + + private static class ConditionalSumB_VectorAPI_V2 { + // Pick B species to be a full vector, and use 4 I vectors of the same bit size. + private static final VectorSpecies SPECIES_B = ByteVector.SPECIES_PREFERRED; + private static final VectorSpecies SPECIES_I = SPECIES_B.vectorShape().withLanes(int.class); + + public static int compute(byte[] a) { + var zeroB = ByteVector.zero(SPECIES_B); + var accI = IntVector.zero(SPECIES_I); + int i; + for (i = 0; i < SPECIES_B.loopBound(a.length); i += SPECIES_B.length()) { + var vB = ByteVector.fromArray(SPECIES_B, a, i); + var maskA = vB.compare(VectorOperators.GE, (byte)'A'); + var maskZ = vB.compare(VectorOperators.LE, (byte)'Z'); + var mask = maskA.and(maskZ); + vB = zeroB.blend(vB, mask); + // When casting byte->int, we get 4x the bits, and split them into 4 parts. + var vI0 = vB.castShape(SPECIES_I, 0); + var vI1 = vB.castShape(SPECIES_I, 1); + var vI2 = vB.castShape(SPECIES_I, 2); + var vI3 = vB.castShape(SPECIES_I, 3); + accI = accI.add(vI0.add(vI1).add(vI2).add(vI3)); + } + int sum = accI.reduceLanes(VectorOperators.ADD); + for (; i < a.length; i++) { + byte c = a[i]; + if (c >= 'A' && c <= 'Z') { + sum += c; + } + } + return sum; + } + } + + public static float[] pieceWise2FunctionF_loop(float[] a, float[] r) { + for (int i = 0; i < a.length; i++) { + float ai = a[i]; + if (ai < 1f) { + float a2 = ai * ai; + float a4 = a2 * a2; + float a8 = a4 * a4; + r[i] = a8; + } else { + float s2 = (float)Math.sqrt(ai); + float s4 = (float)Math.sqrt(s2); + float s8 = (float)Math.sqrt(s4); + r[i] = s8; + } + } + return r; + } + + public static float[] pieceWise2FunctionF_VectorAPI_v1(float[] a, float[] r) { + int i; + for (i = 0; i < SPECIES_F.loopBound(a.length); i += SPECIES_F.length()) { + var ai = FloatVector.fromArray(SPECIES_F, a, i); + var mask = ai.compare(VectorOperators.LT, 1f); + var a2 = ai.lanewise(VectorOperators.MUL, ai); + var a4 = a2.lanewise(VectorOperators.MUL, a2); + var a8 = a4.lanewise(VectorOperators.MUL, a4); + var s2 = ai.lanewise(VectorOperators.SQRT); + var s4 = s2.lanewise(VectorOperators.SQRT); + var s8 = s4.lanewise(VectorOperators.SQRT); + var v = s8.blend(a8, mask); + v.intoArray(r, i); + } + for (; i < a.length; i++) { + float ai = a[i]; + if (ai < 1f) { + float a2 = ai * ai; + float a4 = a2 * a2; + float a8 = a4 * a4; + r[i] = a8; + } else { + float s2 = (float)Math.sqrt(ai); + float s4 = (float)Math.sqrt(s2); + float s8 = (float)Math.sqrt(s4); + r[i] = s8; + } + } + return r; + } + + public static float[] pieceWise2FunctionF_VectorAPI_v2(float[] a, float[] r) { + int i; + for (i = 0; i < SPECIES_F.loopBound(a.length); i += SPECIES_F.length()) { + var ai = FloatVector.fromArray(SPECIES_F, a, i); + var mask = ai.compare(VectorOperators.LT, 1f); + var a2 = ai.lanewise(VectorOperators.MUL, ai); + var a4 = a2.lanewise(VectorOperators.MUL, a2); + var a8 = a4.lanewise(VectorOperators.MUL, a4); + var v = a8; + // SQRT is expensive, so only call if it necessary + if (!mask.allTrue()) { + var s2 = ai.lanewise(VectorOperators.SQRT); + var s4 = s2.lanewise(VectorOperators.SQRT); + var s8 = s4.lanewise(VectorOperators.SQRT); + v = s8.blend(a8, mask); + } + v.intoArray(r, i); + } + for (; i < a.length; i++) { + float ai = a[i]; + if (ai < 1f) { + float a2 = ai * ai; + float a4 = a2 * a2; + float a8 = a4 * a4; + r[i] = a8; + } else { + float s2 = (float)Math.sqrt(ai); + float s4 = (float)Math.sqrt(s2); + float s8 = (float)Math.sqrt(s4); + r[i] = s8; + } + } + return r; + } } diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java index 911494cb022..f60dfcb2d7c 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithms.java @@ -51,13 +51,20 @@ import org.openjdk.jmh.annotations.*; @State(Scope.Thread) @Warmup(iterations = 5, time = 1) @Measurement(iterations = 3, time = 1) -@Fork(value = 5, jvmArgs = {"--add-modules=jdk.incubator.vector", "-XX:CompileCommand=inline,*VectorAlgorithmsImpl*::*"}) +@Fork(value = 1, jvmArgs = {"--add-modules=jdk.incubator.vector", "-XX:CompileCommand=inline,*VectorAlgorithmsImpl*::*"}) public class VectorAlgorithms { @Param({"640000"}) public int SIZE; + // Specifies the length of the arrays / number of elements in the container. @Param({"10000"}) public int NUM_X_OBJECTS; + // Number of simulated "objects" in the "reduceAddIFieldsX4" benchmark. + + @Param({"0.5"}) + public float BRANCH_PROBABILITY; + // Branch probability for the following benchmarks: + // - filterI @Param({"0"}) public int SEED; @@ -66,7 +73,7 @@ public class VectorAlgorithms { @Setup public void init() { - d = new VectorAlgorithmsImpl.Data(SIZE, SEED, NUM_X_OBJECTS); + d = new VectorAlgorithmsImpl.Data(SIZE, SEED, NUM_X_OBJECTS, BRANCH_PROBABILITY); } // ------------------------------------------------------------------------------------------ @@ -208,15 +215,15 @@ public class VectorAlgorithms { // Every invocation should have a different value for e, so that // we don't get branch-prediction that is too good. And also so // that the position where we exit is more evenly distributed. - d.eI_idx = (d.eI_idx + 1) & 0xffff; - int e = d.eI[d.eI_idx]; + d.eI_findI_idx = (d.eI_findI_idx + 1) & 0xffff; + int e = d.eI_findI[d.eI_findI_idx]; return VectorAlgorithmsImpl.findI_loop(d.aI, e); } @Benchmark public int findI_VectorAPI() { - d.eI_idx = (d.eI_idx + 1) & 0xffff; - int e = d.eI[d.eI_idx]; + d.eI_findI_idx = (d.eI_findI_idx + 1) & 0xffff; + int e = d.eI_findI[d.eI_findI_idx]; return VectorAlgorithmsImpl.findI_VectorAPI(d.aI, e); } @@ -235,16 +242,27 @@ public class VectorAlgorithms { // Every invocation should have a different value for e, so that // we don't get branch-prediction that is too good. And also so // That the length of the resulting data is more evenly distributed. - d.eI_idx = (d.eI_idx + 1) & 0xffff; - int e = d.eI[d.eI_idx]; - return VectorAlgorithmsImpl.filterI_loop(d.aI, d.rI1, e); + return VectorAlgorithmsImpl.filterI_loop(d.aI_filterI, d.rI1, d.eI_filterI); } @Benchmark - public Object filterI_VectorAPI() { - d.eI_idx = (d.eI_idx + 1) & 0xffff; - int e = d.eI[d.eI_idx]; - return VectorAlgorithmsImpl.filterI_VectorAPI(d.aI, d.rI1, e); + public Object filterI_VectorAPI_v1() { + return VectorAlgorithmsImpl.filterI_VectorAPI_v1(d.aI_filterI, d.rI1, d.eI_filterI); + } + + @Benchmark + public Object filterI_VectorAPI_v2_l2() { + return VectorAlgorithmsImpl.filterI_VectorAPI_v2_l2(d.aI_filterI, d.rI1, d.eI_filterI); + } + + @Benchmark + public Object filterI_VectorAPI_v2_l4() { + return VectorAlgorithmsImpl.filterI_VectorAPI_v2_l4(d.aI_filterI, d.rI1, d.eI_filterI); + } + + @Benchmark + public Object filterI_VectorAPI_v2_l8() { + return VectorAlgorithmsImpl.filterI_VectorAPI_v2_l8(d.aI_filterI, d.rI1, d.eI_filterI); } @Benchmark @@ -271,4 +289,34 @@ public class VectorAlgorithms { public Object lowerCaseB_VectorAPI_v2() { return VectorAlgorithmsImpl.lowerCaseB_VectorAPI_v2(d.strB, d.rB1); } + + @Benchmark + public Object conditionalSumB_loop() { + return VectorAlgorithmsImpl.conditionalSumB_loop(d.strB); + } + + @Benchmark + public Object conditionalSumB_VectorAPI_v1() { + return VectorAlgorithmsImpl.conditionalSumB_VectorAPI_v1(d.strB); + } + + @Benchmark + public Object conditionalSumB_VectorAPI_v2() { + return VectorAlgorithmsImpl.conditionalSumB_VectorAPI_v2(d.strB); + } + + @Benchmark + public float[] pieceWise2FunctionF_loop() { + return VectorAlgorithmsImpl.pieceWise2FunctionF_loop(d.xF, d.rF1); + } + + @Benchmark + public float[] pieceWise2FunctionF_VectorAPI_v1() { + return VectorAlgorithmsImpl.pieceWise2FunctionF_VectorAPI_v1(d.xF, d.rF1); + } + + @Benchmark + public float[] pieceWise2FunctionF_VectorAPI_v2() { + return VectorAlgorithmsImpl.pieceWise2FunctionF_VectorAPI_v2(d.xF, d.rF1); + } } diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java index 5ab057329d3..3ae4ed81634 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorAlgorithmsImpl.java @@ -36,6 +36,8 @@ public class VectorAlgorithmsImpl { private static final VectorSpecies SPECIES_I = IntVector.SPECIES_PREFERRED; private static final VectorSpecies SPECIES_I512 = IntVector.SPECIES_512; private static final VectorSpecies SPECIES_I256 = IntVector.SPECIES_256; + private static final VectorSpecies SPECIES_I128 = IntVector.SPECIES_128; + private static final VectorSpecies SPECIES_I64 = IntVector.SPECIES_64; private static final VectorSpecies SPECIES_B = ByteVector.SPECIES_PREFERRED; private static final VectorSpecies SPECIES_B64 = ByteVector.SPECIES_64; private static final VectorSpecies SPECIES_F = FloatVector.SPECIES_PREFERRED; @@ -58,15 +60,31 @@ public class VectorAlgorithmsImpl { public int[] rI2; public int[] rI3; public int[] rI4; - public int[] eI; + public int[] rI5; + + // Search element for "findI" + public int[] eI_findI; // The test has to use the same index into eI for all implementations. But in the // benchmark, we'd like to use random indices, so we use the index to advance through // the array. - public int eI_idx = 0; + public int eI_findI_idx = 0; + + // Data and threshold eI value for "filterI". + // We create the data in a range, and then pick a threshold scaled to that range, + // so that the branch in the filter is branchProbability. + public int[] aI_filterI; + public int eI_filterI; public float[] aF; public float[] bF; + // Input for piece-wise functions. + // Uniform [0..1[ with probability p and Uniform [1..2[ with probability (1-p) + public float[] xF; + public float[] rF1; + public float[] rF2; + public float[] rF3; + public byte[] aB; public byte[] strB; public byte[] rB1; @@ -76,7 +94,7 @@ public class VectorAlgorithmsImpl { public int[] oopsX4; public int[] memX4; - public Data(int size, int seed, int numX4Objects) { + public Data(int size, int seed, int numX4Objects, float branchProbability) { Random random = new Random(seed); // int: one input array and multiple output arrays so different implementations can @@ -86,14 +104,20 @@ public class VectorAlgorithmsImpl { rI2 = new int[size]; rI3 = new int[size]; rI4 = new int[size]; + rI5 = new int[size]; Arrays.setAll(aI, i -> random.nextInt()); // Populate with some random values from aI, and some totally random values. - eI = new int[0x10000]; - for (int i = 0; i < eI.length; i++) { - eI[i] = (random.nextInt(10) == 0) ? random.nextInt() : aI[random.nextInt(size)]; + eI_findI = new int[0x10000]; + for (int i = 0; i < eI_findI.length; i++) { + eI_findI[i] = (random.nextInt(10) == 0) ? random.nextInt() : aI[random.nextInt(size)]; } + int filterI_range = 1000_000; + aI_filterI = new int[size]; + Arrays.setAll(aI_filterI, i -> random.nextInt(filterI_range)); + eI_filterI = (int)(filterI_range * (1.0f - branchProbability)); + // X4 oop setup. // oopsX4 holds "addresses" (i.e. indices), that point to the 16-byte objects in memX4. oopsX4 = new int[size]; @@ -117,14 +141,30 @@ public class VectorAlgorithmsImpl { bF[i] = random.nextInt(32) - 16; } + xF = new float[size]; + rF1 = new float[size]; + rF2 = new float[size]; + rF3 = new float[size]; + for (int i = 0; i < size; i++) { + xF[i] = (random.nextFloat() < branchProbability) + ? 0f + random.nextFloat() + : 1f + random.nextFloat(); + } + // byte: just random data. aB = new byte[size]; - strB = new byte[size]; rB1 = new byte[size]; rB2 = new byte[size]; rB3 = new byte[size]; random.nextBytes(aB); - random.nextBytes(strB); // TODO: special data! + + // byte string: for lowerCase benchmark. + strB = new byte[size]; + for (int i = 0; i < size; i++) { + strB[i] = (random.nextFloat() < branchProbability) + ? (byte)(random.nextInt(16) + 'A') + : (byte)(random.nextInt(16) + 'a'); + } } } @@ -651,13 +691,12 @@ public class VectorAlgorithmsImpl { return r; } - public static Object filterI_VectorAPI(int[] a, int[] r, int threshold) { - var thresholds = IntVector.broadcast(SPECIES_I, threshold); + public static Object filterI_VectorAPI_v1(int[] a, int[] r, int threshold) { int j = 0; int i = 0; for (; i < SPECIES_I.loopBound(a.length); i += SPECIES_I.length()) { IntVector v = IntVector.fromArray(SPECIES_I, a, i); - var mask = v.compare(VectorOperators.GE, thresholds); + var mask = v.compare(VectorOperators.GE, threshold); v = v.compress(mask); int trueCount = mask.trueCount(); var prefixMask = mask.compress(); @@ -676,6 +715,98 @@ public class VectorAlgorithmsImpl { return r; } + // Idea: on platforms that do not support the "v1" solution with "compress" and + // masked stores, we struggle to deal with the loop-carried dependency of j. + // But we can still use dynamic uniformity to enable some vectorized performance. + public static Object filterI_VectorAPI_v2_l2(int[] a, int[] r, int threshold) { + int j = 0; + int i = 0; + for (; i < SPECIES_I64.loopBound(a.length); i += SPECIES_I64.length()) { + IntVector v = IntVector.fromArray(SPECIES_I64, a, i); + var mask = v.compare(VectorOperators.GE, threshold); + if (mask.allTrue()) { + v.intoArray(r, j); + j += 2; + } else if (mask.anyTrue()) { + if (mask.laneIsSet(0)) { r[j++] = v.lane(0); } + if (mask.laneIsSet(1)) { r[j++] = v.lane(1); } + } else { + // nothing + } + } + for (; i < a.length; i++) { + int ai = a[i]; + if (ai >= threshold) { + r[j++] = ai; + } + } + // Just force the resulting length onto the same array. + r[r.length - 1] = j; + return r; + } + + public static Object filterI_VectorAPI_v2_l4(int[] a, int[] r, int threshold) { + int j = 0; + int i = 0; + for (; i < SPECIES_I128.loopBound(a.length); i += SPECIES_I128.length()) { + IntVector v = IntVector.fromArray(SPECIES_I128, a, i); + var mask = v.compare(VectorOperators.GE, threshold); + if (mask.allTrue()) { + v.intoArray(r, j); + j += 4; + } else if (mask.anyTrue()) { + if (mask.laneIsSet(0)) { r[j++] = v.lane(0); } + if (mask.laneIsSet(1)) { r[j++] = v.lane(1); } + if (mask.laneIsSet(2)) { r[j++] = v.lane(2); } + if (mask.laneIsSet(3)) { r[j++] = v.lane(3); } + } else { + // nothing + } + } + for (; i < a.length; i++) { + int ai = a[i]; + if (ai >= threshold) { + r[j++] = ai; + } + } + // Just force the resulting length onto the same array. + r[r.length - 1] = j; + return r; + } + + public static Object filterI_VectorAPI_v2_l8(int[] a, int[] r, int threshold) { + int j = 0; + int i = 0; + for (; i < SPECIES_I256.loopBound(a.length); i += SPECIES_I256.length()) { + IntVector v = IntVector.fromArray(SPECIES_I256, a, i); + var mask = v.compare(VectorOperators.GE, threshold); + if (mask.allTrue()) { + v.intoArray(r, j); + j += 8; + } else if (mask.anyTrue()) { + if (mask.laneIsSet(0)) { r[j++] = v.lane(0); } + if (mask.laneIsSet(1)) { r[j++] = v.lane(1); } + if (mask.laneIsSet(2)) { r[j++] = v.lane(2); } + if (mask.laneIsSet(3)) { r[j++] = v.lane(3); } + if (mask.laneIsSet(4)) { r[j++] = v.lane(4); } + if (mask.laneIsSet(5)) { r[j++] = v.lane(5); } + if (mask.laneIsSet(6)) { r[j++] = v.lane(6); } + if (mask.laneIsSet(7)) { r[j++] = v.lane(7); } + } else { + // nothing + } + } + for (; i < a.length; i++) { + int ai = a[i]; + if (ai >= threshold) { + r[j++] = ai; + } + } + // Just force the resulting length onto the same array. + r[r.length - 1] = j; + return r; + } + // X4: ints simulate 4-byte oops. // oops: if non-zero (= non-null), every entry simulates a 4-byte oop, pointing into mem. // mem: an int array that simulates the memory. @@ -771,5 +902,176 @@ public class VectorAlgorithmsImpl { } return r; } -} + public static int conditionalSumB_loop(byte[] a) { + int sum = 0; + for (int i = 0; i < a.length; i++) { + byte c = a[i]; + if (c >= 'A' && c <= 'Z') { + sum += c; + } + } + return sum; + } + + public static int conditionalSumB_VectorAPI_v1(byte[] a) { + return ConditionalSumB_VectorAPI_V1.compute(a); + } + + private static class ConditionalSumB_VectorAPI_V1 { + // Pick I species to be a full vector, and the B vector a quarter its bit length. + // However, we have to get at least 64bits for the B vector, so at least 256bits + // for the int vector - a sad restriction by the currently very narrow range of + // supported shapes. + private static final int BITS_I = Math.max(256, IntVector.SPECIES_PREFERRED.vectorBitSize()); + private static final int BITS_B = BITS_I / 4; + private static final VectorShape SHAPE_I = VectorShape.forBitSize(BITS_I); + private static final VectorShape SHAPE_B = VectorShape.forBitSize(BITS_B); + private static final VectorSpecies SPECIES_I = SHAPE_I.withLanes(int.class); + private static final VectorSpecies SPECIES_B = SHAPE_B.withLanes(byte.class); + + public static int compute(byte[] a) { + var zeroB = ByteVector.zero(SPECIES_B); + var accI = IntVector.zero(SPECIES_I); + int i; + for (i = 0; i < SPECIES_B.loopBound(a.length); i += SPECIES_B.length()) { + var vB = ByteVector.fromArray(SPECIES_B, a, i); + var maskA = vB.compare(VectorOperators.GE, (byte)'A'); + var maskZ = vB.compare(VectorOperators.LE, (byte)'Z'); + var mask = maskA.and(maskZ); + vB = zeroB.blend(vB, mask); + var vI = vB.castShape(SPECIES_I, 0); + accI = accI.add(vI); + } + int sum = accI.reduceLanes(VectorOperators.ADD); + for (; i < a.length; i++) { + byte c = a[i]; + if (c >= 'A' && c <= 'Z') { + sum += c; + } + } + return sum; + } + } + + public static int conditionalSumB_VectorAPI_v2(byte[] a) { + return ConditionalSumB_VectorAPI_V2.compute(a); + } + + private static class ConditionalSumB_VectorAPI_V2 { + // Pick B species to be a full vector, and use 4 I vectors of the same bit size. + private static final VectorSpecies SPECIES_B = ByteVector.SPECIES_PREFERRED; + private static final VectorSpecies SPECIES_I = SPECIES_B.vectorShape().withLanes(int.class); + + public static int compute(byte[] a) { + var zeroB = ByteVector.zero(SPECIES_B); + var accI = IntVector.zero(SPECIES_I); + int i; + for (i = 0; i < SPECIES_B.loopBound(a.length); i += SPECIES_B.length()) { + var vB = ByteVector.fromArray(SPECIES_B, a, i); + var maskA = vB.compare(VectorOperators.GE, (byte)'A'); + var maskZ = vB.compare(VectorOperators.LE, (byte)'Z'); + var mask = maskA.and(maskZ); + vB = zeroB.blend(vB, mask); + // When casting byte->int, we get 4x the bits, and split them into 4 parts. + var vI0 = vB.castShape(SPECIES_I, 0); + var vI1 = vB.castShape(SPECIES_I, 1); + var vI2 = vB.castShape(SPECIES_I, 2); + var vI3 = vB.castShape(SPECIES_I, 3); + accI = accI.add(vI0.add(vI1).add(vI2).add(vI3)); + } + int sum = accI.reduceLanes(VectorOperators.ADD); + for (; i < a.length; i++) { + byte c = a[i]; + if (c >= 'A' && c <= 'Z') { + sum += c; + } + } + return sum; + } + } + + public static float[] pieceWise2FunctionF_loop(float[] a, float[] r) { + for (int i = 0; i < a.length; i++) { + float ai = a[i]; + if (ai < 1f) { + float a2 = ai * ai; + float a4 = a2 * a2; + float a8 = a4 * a4; + r[i] = a8; + } else { + float s2 = (float)Math.sqrt(ai); + float s4 = (float)Math.sqrt(s2); + float s8 = (float)Math.sqrt(s4); + r[i] = s8; + } + } + return r; + } + + public static float[] pieceWise2FunctionF_VectorAPI_v1(float[] a, float[] r) { + int i; + for (i = 0; i < SPECIES_F.loopBound(a.length); i += SPECIES_F.length()) { + var ai = FloatVector.fromArray(SPECIES_F, a, i); + var mask = ai.compare(VectorOperators.LT, 1f); + var a2 = ai.lanewise(VectorOperators.MUL, ai); + var a4 = a2.lanewise(VectorOperators.MUL, a2); + var a8 = a4.lanewise(VectorOperators.MUL, a4); + var s2 = ai.lanewise(VectorOperators.SQRT); + var s4 = s2.lanewise(VectorOperators.SQRT); + var s8 = s4.lanewise(VectorOperators.SQRT); + var v = s8.blend(a8, mask); + v.intoArray(r, i); + } + for (; i < a.length; i++) { + float ai = a[i]; + if (ai < 1f) { + float a2 = ai * ai; + float a4 = a2 * a2; + float a8 = a4 * a4; + r[i] = a8; + } else { + float s2 = (float)Math.sqrt(ai); + float s4 = (float)Math.sqrt(s2); + float s8 = (float)Math.sqrt(s4); + r[i] = s8; + } + } + return r; + } + + public static float[] pieceWise2FunctionF_VectorAPI_v2(float[] a, float[] r) { + int i; + for (i = 0; i < SPECIES_F.loopBound(a.length); i += SPECIES_F.length()) { + var ai = FloatVector.fromArray(SPECIES_F, a, i); + var mask = ai.compare(VectorOperators.LT, 1f); + var a2 = ai.lanewise(VectorOperators.MUL, ai); + var a4 = a2.lanewise(VectorOperators.MUL, a2); + var a8 = a4.lanewise(VectorOperators.MUL, a4); + var v = a8; + // SQRT is expensive, so only call if it necessary + if (!mask.allTrue()) { + var s2 = ai.lanewise(VectorOperators.SQRT); + var s4 = s2.lanewise(VectorOperators.SQRT); + var s8 = s4.lanewise(VectorOperators.SQRT); + v = s8.blend(a8, mask); + } + v.intoArray(r, i); + } + for (; i < a.length; i++) { + float ai = a[i]; + if (ai < 1f) { + float a2 = ai * ai; + float a4 = a2 * a2; + float a8 = a4 * a4; + r[i] = a8; + } else { + float s2 = (float)Math.sqrt(ai); + float s4 = (float)Math.sqrt(s2); + float s8 = (float)Math.sqrt(s4); + r[i] = s8; + } + } + return r; + } +} From c3dfceb90a616208880d6bc5a7e3098a493a25a8 Mon Sep 17 00:00:00 2001 From: Johny Jose Date: Mon, 9 Mar 2026 07:55:28 +0000 Subject: [PATCH 103/170] 8379035: (tz) Update Timezone Data to 2026a Reviewed-by: coffeys, naoto --- src/java.base/share/data/tzdata/VERSION | 2 +- src/java.base/share/data/tzdata/etcetera | 3 +- src/java.base/share/data/tzdata/europe | 74 +++++++++++++++++-- src/java.base/share/data/tzdata/leapseconds | 8 +- .../java/util/TimeZone/TimeZoneData/VERSION | 2 +- 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/data/tzdata/VERSION b/src/java.base/share/data/tzdata/VERSION index ce25e7653b0..a2974d757c8 100644 --- a/src/java.base/share/data/tzdata/VERSION +++ b/src/java.base/share/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2025c +tzdata2026a diff --git a/src/java.base/share/data/tzdata/etcetera b/src/java.base/share/data/tzdata/etcetera index 41660b05dba..9b030fdb8d4 100644 --- a/src/java.base/share/data/tzdata/etcetera +++ b/src/java.base/share/data/tzdata/etcetera @@ -43,7 +43,8 @@ # which load the "UTC" file to handle seconds properly. Zone Etc/UTC 0 - UTC -# Functions like gmtime load the "GMT" file to handle leap seconds properly. +# If leap second support is enabled, functions like gmtime +# load the "GMT" file to handle leap seconds properly. # Vanguard section, which works with most .zi parsers. #Zone GMT 0 - GMT # Rearguard section, for TZUpdater 2.3.2 and earlier. diff --git a/src/java.base/share/data/tzdata/europe b/src/java.base/share/data/tzdata/europe index b82ca6f67bb..a66d40834cd 100644 --- a/src/java.base/share/data/tzdata/europe +++ b/src/java.base/share/data/tzdata/europe @@ -1064,9 +1064,19 @@ Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Tórshavn # Greenland # -# From Paul Eggert (2004-10-31): +# From Paul Eggert (2026-01-22): +# During World War II, Greenland was effectively independent of Denmark and +# observed daylight saving time. TIME, volume 37, page 23 (1941-04-21) +# says, +# "Penfield and West made their way to the U.S.'s most northerly consulate. +# They were astonished to find that Greenlanders, with almost 24 hours of +# sunlight a day during the summer, have daylight saving time." +# As the details are unknown they are omitted from the data for now. +# # During World War II, Germany maintained secret manned weather stations in # East Greenland and Franz Josef Land, but we don't know their time zones. +# Also, they're likely out of scope for the database +# as we lack resources to track every bit of military activity. # My source for this is Wilhelm Dege's book mentioned under Svalbard. # # From Paul Eggert (2017-12-10): @@ -1980,7 +1990,6 @@ Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 # Valletta # From Stepan Golosunov (2016-03-07): # the act of the government of the Republic of Moldova Nr. 132 from 1990-05-04 -# http://lex.justice.md/viewdoc.php?action=view&view=doc&id=298782&lang=2 # ... says that since 1990-05-06 on the territory of the Moldavian SSR # time would be calculated as the standard time of the second time belt # plus one hour of the "summer" time. To implement that clocks would be @@ -2035,9 +2044,61 @@ Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 # Valletta # says the 2014-03-30 spring-forward transition was at 02:00 local time. # Guess that since 1997 Moldova has switched one hour before the EU. +# From Heitor David Pinto (2026-02-22): +# Soviet Moldovan resolution 132 of 1990 defined the summer time period from +# the last Sunday in March at 2:00 to the last Sunday in September at 3:00, +# matching the dates used in most of Europe at the time: +# https://web.archive.org/web/20211107050832/http://lex.justice.md/viewdoc.php?action=view&view=doc&id=298782&lang=1 +# +# It seems that in 1996 Moldova changed the end date to October like most of +# Europe, but kept the transitions at 2:00 and 3:00 rather than 1:00 UTC, +# which would have been locally 3:00 and 4:00.... +# +# The notices in the Moldovan government website and broadcaster showed the +# transitions at 2:00 and 3:00 until 2021: +# 2015 https://old.gov.md/en/node/7304 +# 2016 https://old.gov.md/en/node/12587 +# 2017 https://old.gov.md/en/node/20654 +# 2017 https://old.gov.md/en/content/moldova-upholds-winter-time-night-28-29-october +# 2018 https://old.gov.md/en/content/moldova-switch-summer-time +# 2018 https://old.gov.md/en/content/cabinet-ministers-informs-about-switch-winter-time-28-october +# 2019 https://old.gov.md/en/content/moldova-switch-summer-time-31-march +# 2019 https://old.gov.md/en/node/31122 +# 2020 https://old.gov.md/en/node/32771 +# 2020 https://old.gov.md/en/node/34497 +# 2021 https://trm.md/ro/social/moldova-trece-in-aceasta-noapte-la-ora-de-vara +# 2021 https://trm.md/en/social/republica-moldova-trece-la-ora-de-iarna1 +# +# However, since 2022, the notices showed the transitions at 3:00 and 4:00, +# matching the EU rule at 1:00 UTC: +# 2022 https://trm.md/en/social/in-acest-weekend-republica-moldova-trece-la-ora-de-vara +# 2022 https://old.gov.md/en/content/moldova-switch-winter-time +# 2023 https://moldova1.md/p/6587/ora-de-vara-2023-cum-schimbam-acele-ceasornicelor-si-cand-trecem-la-ora-de-vara +# 2023 https://old.gov.md/en/node/46662 +# 2024 https://moldova1.md/p/26535/republica-moldova-trece-la-ora-de-vara-in-acest-weekend +# 2024 https://moldova1.md/p/37768/republica-moldova-trece-in-aceasta-noapte-la-ora-de-iarna +# 2025 https://moldova1.md/p/46349/republica-moldova-trece-la-ora-de-vara-pe-30-martie-cum-ne-afecteaza-si-ce-recomanda-medicii +# 2025 https://moldova1.md/p/60469/republica-moldova-trece-la-ora-de-iarna-ceasurile-se-dau-inapoi-cu-o-ora +# +# It seems that the changes to the end date and transition times were just +# done in practice without formally changing the resolution. In late 2025, the +# government said that the Soviet resolution was still in force, and proposed +# a new resolution to replace it and formally establish the EU rule: +# ... based on the notices, it seems that in practice Moldova already +# uses the EU rule since 2022. This was also the year when Moldova applied to +# join the EU. +# +# From Robert Bastian (2026-02-26): +# This has been approved and published in the government gazette: +# https://monitorul.gov.md/ro/monitorul/view/pdf/3234/part/2#page=27 +# +# From Paul Eggert (2026-02-24): +# Also see Svetlana Rudenko, "Moldova abandons the 'Soviet era'", Logos Press, +# 2026-02-21 . + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule Moldova 1997 max - Mar lastSun 2:00 1:00 S -Rule Moldova 1997 max - Oct lastSun 3:00 0 - +Rule Moldova 1997 2021 - Mar lastSun 2:00 1:00 S +Rule Moldova 1997 2021 - Oct lastSun 3:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Europe/Chisinau 1:55:20 - LMT 1880 @@ -2050,7 +2111,8 @@ Zone Europe/Chisinau 1:55:20 - LMT 1880 2:00 Russia EE%sT 1992 2:00 E-Eur EE%sT 1997 # See Romania commentary for the guessed 1997 transition to EU rules. - 2:00 Moldova EE%sT + 2:00 Moldova EE%sT 2022 + 2:00 EU EE%sT # Poland @@ -2436,7 +2498,7 @@ Zone Atlantic/Madeira -1:07:36 - LMT 1884 # Funchal # Nine O'clock # (1998-10-23) reports that the switch occurred at # 04:00 local time in fall 1998. For lack of better info, -# assume that Romania and Moldova switched to EU rules in 1997, +# assume that Romania switched to EU rules in 1997, # the same year as Bulgaria. # # Rule NAME FROM TO - IN ON AT SAVE LETTER/S diff --git a/src/java.base/share/data/tzdata/leapseconds b/src/java.base/share/data/tzdata/leapseconds index 9426b40f07e..d431a7d3607 100644 --- a/src/java.base/share/data/tzdata/leapseconds +++ b/src/java.base/share/data/tzdata/leapseconds @@ -93,7 +93,7 @@ Leap 2016 Dec 31 23:59:60 + S # Any additional leap seconds will come after this. # This Expires line is commented out for now, # so that pre-2020a zic implementations do not reject this file. -#Expires 2026 Jun 28 00:00:00 +#Expires 2026 Dec 28 00:00:00 # Here are POSIX timestamps for the data in this file. # "#updated" gives the last time the leap seconds data changed @@ -102,8 +102,8 @@ Leap 2016 Dec 31 23:59:60 + S # "#expires" gives the first time this file might be wrong; # if this file was derived from the IERS leap-seconds.list, # this is typically a bit less than one year after "updated". -#updated 1751846400 (2025-07-07 00:00:00 UTC) -#expires 1782604800 (2026-06-28 00:00:00 UTC) +#updated 1767698058 (2026-01-06 11:14:18 UTC) +#expires 1798416000 (2026-12-28 00:00:00 UTC) # Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat) -# File expires on 28 June 2026 +# File expires on 28 December 2026 diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION index 76d146afc71..2f72d7dbcb2 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION +++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION @@ -1 +1 @@ -tzdata2025c +tzdata2026a From 08198e7fd9d83973aba6f6da6ab985065244cccc Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 9 Mar 2026 08:01:23 +0000 Subject: [PATCH 104/170] 8379297: Serial: Replace CSpaceCounters with HSpaceCounters Reviewed-by: stefank, tschatzl --- .../share/gc/serial/cSpaceCounters.cpp | 83 ------------------- .../share/gc/serial/cSpaceCounters.hpp | 62 -------------- .../share/gc/serial/defNewGeneration.cpp | 21 ++--- .../share/gc/serial/defNewGeneration.hpp | 9 +- .../share/gc/serial/tenuredGeneration.cpp | 7 +- .../share/gc/serial/tenuredGeneration.hpp | 4 +- 6 files changed, 21 insertions(+), 165 deletions(-) delete mode 100644 src/hotspot/share/gc/serial/cSpaceCounters.cpp delete mode 100644 src/hotspot/share/gc/serial/cSpaceCounters.hpp diff --git a/src/hotspot/share/gc/serial/cSpaceCounters.cpp b/src/hotspot/share/gc/serial/cSpaceCounters.cpp deleted file mode 100644 index f6bcee99423..00000000000 --- a/src/hotspot/share/gc/serial/cSpaceCounters.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "gc/serial/cSpaceCounters.hpp" -#include "memory/allocation.inline.hpp" -#include "memory/resourceArea.hpp" - -CSpaceCounters::CSpaceCounters(const char* name, int ordinal, size_t max_size, - ContiguousSpace* s, GenerationCounters* gc) - : _space(s) { - if (UsePerfData) { - EXCEPTION_MARK; - ResourceMark rm; - - const char* cns = PerfDataManager::name_space(gc->name_space(), "space", - ordinal); - - _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC); - strcpy(_name_space, cns); - - const char* cname = PerfDataManager::counter_name(_name_space, "name"); - PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK); - - cname = PerfDataManager::counter_name(_name_space, "maxCapacity"); - _max_capacity = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Bytes, - (jlong)max_size, - CHECK); - - cname = PerfDataManager::counter_name(_name_space, "capacity"); - _capacity = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Bytes, - _space->capacity(), - CHECK); - - cname = PerfDataManager::counter_name(_name_space, "used"); - _used = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, - _space->used(), - CHECK); - - cname = PerfDataManager::counter_name(_name_space, "initCapacity"); - PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, - _space->capacity(), CHECK); - } -} - -CSpaceCounters::~CSpaceCounters() { - FREE_C_HEAP_ARRAY(char, _name_space); -} - -void CSpaceCounters::update_capacity() { - _capacity->set_value(_space->capacity()); -} - -void CSpaceCounters::update_used() { - _used->set_value(_space->used()); -} - -void CSpaceCounters::update_all() { - update_used(); - update_capacity(); -} diff --git a/src/hotspot/share/gc/serial/cSpaceCounters.hpp b/src/hotspot/share/gc/serial/cSpaceCounters.hpp deleted file mode 100644 index 22a51cbbd20..00000000000 --- a/src/hotspot/share/gc/serial/cSpaceCounters.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_GC_SERIAL_CSPACECOUNTERS_HPP -#define SHARE_GC_SERIAL_CSPACECOUNTERS_HPP - -#include "gc/shared/generationCounters.hpp" -#include "gc/shared/space.hpp" -#include "runtime/perfData.hpp" - -// A CSpaceCounters is a holder class for performance counters -// that track a space; - -class CSpaceCounters: public CHeapObj { - private: - PerfVariable* _capacity; - PerfVariable* _used; - PerfVariable* _max_capacity; - - // Constant PerfData types don't need to retain a reference. - // However, it's a good idea to document them here. - // PerfConstant* _size; - - ContiguousSpace* _space; - char* _name_space; - - public: - - CSpaceCounters(const char* name, int ordinal, size_t max_size, - ContiguousSpace* s, GenerationCounters* gc); - - ~CSpaceCounters(); - - void update_capacity(); - void update_used(); - void update_all(); - - const char* name_space() const { return _name_space; } -}; - -#endif // SHARE_GC_SERIAL_CSPACECOUNTERS_HPP diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 9ccc7b95529..225f15f785f 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -39,6 +39,7 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/gcTraceTime.inline.hpp" +#include "gc/shared/hSpaceCounters.hpp" #include "gc/shared/oopStorageSet.inline.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" @@ -248,12 +249,12 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, min_size, max_size, _virtual_space.committed_size()); _gc_counters = new CollectorCounters(policy, 0); - _eden_counters = new CSpaceCounters("eden", 0, _max_eden_size, _eden_space, - _gen_counters); - _from_counters = new CSpaceCounters("s0", 1, _max_survivor_size, _from_space, - _gen_counters); - _to_counters = new CSpaceCounters("s1", 2, _max_survivor_size, _to_space, - _gen_counters); + _eden_counters = new HSpaceCounters(_gen_counters->name_space(), "eden", 0, + _max_eden_size, _eden_space->capacity()); + _from_counters = new HSpaceCounters(_gen_counters->name_space(), "s0", 1, + _max_survivor_size, _from_space->capacity()); + _to_counters = new HSpaceCounters(_gen_counters->name_space(), "s1", 2, + _max_survivor_size, _to_space->capacity()); update_counters(); _old_gen = nullptr; @@ -319,7 +320,7 @@ void DefNewGeneration::swap_spaces() { _to_space = s; if (UsePerfData) { - CSpaceCounters* c = _from_counters; + HSpaceCounters* c = _from_counters; _from_counters = _to_counters; _to_counters = c; } @@ -821,9 +822,9 @@ void DefNewGeneration::gc_epilogue() { void DefNewGeneration::update_counters() { if (UsePerfData) { - _eden_counters->update_all(); - _from_counters->update_all(); - _to_counters->update_all(); + _eden_counters->update_all(_eden_space->capacity(), _eden_space->used()); + _from_counters->update_all(_from_space->capacity(), _from_space->used()); + _to_counters->update_all(_to_space->capacity(), _to_space->used()); _gen_counters->update_capacity(_virtual_space.committed_size()); } } diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index e0c7b6bba37..98e599ffeaf 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -25,7 +25,6 @@ #ifndef SHARE_GC_SERIAL_DEFNEWGENERATION_HPP #define SHARE_GC_SERIAL_DEFNEWGENERATION_HPP -#include "gc/serial/cSpaceCounters.hpp" #include "gc/serial/generation.hpp" #include "gc/serial/tenuredGeneration.hpp" #include "gc/shared/ageTable.hpp" @@ -38,7 +37,7 @@ #include "utilities/stack.hpp" class ContiguousSpace; -class CSpaceCounters; +class HSpaceCounters; class OldGenScanClosure; class YoungGenScanClosure; class DefNewTracer; @@ -102,9 +101,9 @@ class DefNewGeneration: public Generation { // Performance Counters GenerationCounters* _gen_counters; - CSpaceCounters* _eden_counters; - CSpaceCounters* _from_counters; - CSpaceCounters* _to_counters; + HSpaceCounters* _eden_counters; + HSpaceCounters* _from_counters; + HSpaceCounters* _to_counters; // sizing information size_t _max_eden_size; diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index f68847ed1a6..95a996a98c1 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -32,6 +32,7 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/genArguments.hpp" +#include "gc/shared/hSpaceCounters.hpp" #include "gc/shared/space.hpp" #include "gc/shared/spaceDecorator.hpp" #include "logging/log.hpp" @@ -330,9 +331,9 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs, _gc_counters = new CollectorCounters("Serial full collection pauses", 1); - _space_counters = new CSpaceCounters(gen_name, 0, + _space_counters = new HSpaceCounters(_gen_counters->name_space(), gen_name, 0, _virtual_space.reserved_size(), - _the_space, _gen_counters); + _the_space->capacity()); } void TenuredGeneration::gc_prologue() { @@ -367,7 +368,7 @@ void TenuredGeneration::update_promote_stats() { void TenuredGeneration::update_counters() { if (UsePerfData) { - _space_counters->update_all(); + _space_counters->update_all(_the_space->capacity(), _the_space->used()); _gen_counters->update_capacity(_virtual_space.committed_size()); } } diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index ff73ab72b2c..1e3576d5ae7 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -25,7 +25,6 @@ #ifndef SHARE_GC_SERIAL_TENUREDGENERATION_HPP #define SHARE_GC_SERIAL_TENUREDGENERATION_HPP -#include "gc/serial/cSpaceCounters.hpp" #include "gc/serial/generation.hpp" #include "gc/serial/serialBlockOffsetTable.hpp" #include "gc/shared/generationCounters.hpp" @@ -34,6 +33,7 @@ class CardTableRS; class ContiguousSpace; +class HSpaceCounters; // TenuredGeneration models the heap containing old (promoted/tenured) objects // contained in a single contiguous space. This generation is covered by a card @@ -68,7 +68,7 @@ class TenuredGeneration: public Generation { ContiguousSpace* _the_space; // Actual space holding objects GenerationCounters* _gen_counters; - CSpaceCounters* _space_counters; + HSpaceCounters* _space_counters; // Avg amount promoted; used for avoiding promotion undo // This class does not update deviations if the sample is zero. From e22c95cd96f823f75e00396b9ce0701b0eb6c3d5 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Mon, 9 Mar 2026 08:50:25 +0000 Subject: [PATCH 105/170] 8378746: ZGC: jdk/jfr/event/gc/detailed/TestZRelocationSetGroupEvent.java intermittent OOME Reviewed-by: stefank, ayang --- .../jfr/event/gc/detailed/TestZRelocationSetGroupEvent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestZRelocationSetGroupEvent.java b/test/jdk/jdk/jfr/event/gc/detailed/TestZRelocationSetGroupEvent.java index 29e1de24224..8ece7bf12d7 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestZRelocationSetGroupEvent.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestZRelocationSetGroupEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ import jdk.test.lib.jfr.Events; * @requires vm.hasJFR & vm.gc.Z * @requires vm.flagless * @library /test/lib /test/jdk /test/hotspot/jtreg - * @run main/othervm -XX:+UseZGC -Xmx32M jdk.jfr.event.gc.detailed.TestZRelocationSetGroupEvent + * @run main/othervm -XX:+UseZGC -Xmx64M jdk.jfr.event.gc.detailed.TestZRelocationSetGroupEvent */ public class TestZRelocationSetGroupEvent { From 321bf3f1fa04efb1c344fd93b59fea89587eecee Mon Sep 17 00:00:00 2001 From: Michael Reeves Date: Mon, 9 Mar 2026 09:10:19 +0000 Subject: [PATCH 106/170] 8372273: C2: Extend the refactoring for IGV printing to include rest of the node properties Reviewed-by: chagedorn, snatarajan --- src/hotspot/share/opto/idealGraphPrinter.cpp | 109 +++++++++---------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index 5070a9f00e1..563a914ea5c 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -40,16 +40,60 @@ class PrintProperties { private: IdealGraphPrinter* _printer; + void print_alias_properties(Node* node); + void print_escape_properties(Node* node); public: PrintProperties(IdealGraphPrinter* printer) : _printer(printer) {} void print_node_properties(Node* node); + void print_node_details(Node* node); void print_lrg_properties(const LRG& lrg, const char* buffer); void print_property(int flag, const char* name); void print_property(int flag, const char* name, const char* val); void print_property(int flag, const char* name, int val); }; +void PrintProperties::print_alias_properties(Node* node) { + const TypePtr* adr_type = node->adr_type(); + Compile* C = _printer->C; + if (adr_type != nullptr && C->have_alias_type(adr_type)) { + Compile::AliasType* at = C->alias_type(adr_type); + if (at != nullptr) { + print_property(true, "alias_index", at->index()); + // The value of at->field(), if present, is already dumped in the + // "source"/"destination" properties. + const Type* element = at->element(); + if (element != nullptr) { + stringStream element_stream; + element->dump_on(&element_stream); + print_property(true, "alias_element", element_stream.freeze()); + } + print_property(at->is_rewritable(), "alias_is_rewritable"); + print_property(at->is_volatile(), "alias_is_volatile"); + print_property(at->general_index() != at->index(), "alias_general_index", at->general_index()); + } + } +} + +void PrintProperties::print_escape_properties(Node* node) { + // Dump escape analysis state for relevant nodes. + if (node->is_Allocate()) { + AllocateNode* alloc = node->as_Allocate(); + print_property(alloc->_is_scalar_replaceable, "is_scalar_replaceable"); + print_property(alloc->_is_non_escaping, "is_non_escaping"); + print_property(alloc->does_not_escape_thread(), "does_not_escape_thread"); + } + if (node->is_SafePoint() && node->as_SafePoint()->has_ea_local_in_scope()) { + print_property(true, "has_ea_local_in_scope"); + } + if (node->is_CallJava() && node->as_CallJava()->arg_escape()) { + print_property(true, "arg_escape"); + } + if (node->is_Initialize() && node->as_Initialize()->does_not_escape()) { + print_property(true, "does_not_escape"); + } +} + void PrintProperties::print_node_properties(Node* node) { const jushort flags = node->flags(); print_property((flags & Node::Flag_is_Copy), "is_copy"); @@ -75,6 +119,15 @@ void PrintProperties::print_node_properties(Node* node) { } } +void PrintProperties::print_node_details(Node* node) { + print_alias_properties(node); + + print_escape_properties(node); + + print_property(node->is_block_proj() != nullptr, "is_block_proj"); + print_property(node->is_block_start(), "is_block_start"); +} + void PrintProperties::print_lrg_properties(const LRG &lrg, const char *buffer) { print_property(true, "mask", buffer); print_property(true, "mask_size", lrg.mask_size()); @@ -651,61 +704,7 @@ void IdealGraphPrinter::visit_node(Node* n, bool edges) { assert(s2.size() < sizeof(buffer), "size in range"); print_prop("dump_spec", buffer); - const TypePtr* adr_type = node->adr_type(); - if (adr_type != nullptr && C->have_alias_type(adr_type)) { - Compile::AliasType* at = C->alias_type(adr_type); - if (at != nullptr) { - print_prop("alias_index", at->index()); - // The value of at->field(), if present, is already dumped in the - // "source"/"destination" properties. - const Type* element = at->element(); - if (element != nullptr) { - stringStream element_stream; - element->dump_on(&element_stream); - print_prop("alias_element", element_stream.freeze()); - } - if (at->is_rewritable()) { - print_prop("alias_is_rewritable", "true"); - } - if (at->is_volatile()) { - print_prop("alias_is_volatile", "true"); - } - if (at->general_index() != at->index()) { - print_prop("alias_general_index", at->general_index()); - } - } - } - - if (node->is_block_proj()) { - print_prop("is_block_proj", "true"); - } - - if (node->is_block_start()) { - print_prop("is_block_start", "true"); - } - - // Dump escape analysis state for relevant nodes. - if (node->is_Allocate()) { - AllocateNode* alloc = node->as_Allocate(); - if (alloc->_is_scalar_replaceable) { - print_prop("is_scalar_replaceable", "true"); - } - if (alloc->_is_non_escaping) { - print_prop("is_non_escaping", "true"); - } - if (alloc->does_not_escape_thread()) { - print_prop("does_not_escape_thread", "true"); - } - } - if (node->is_SafePoint() && node->as_SafePoint()->has_ea_local_in_scope()) { - print_prop("has_ea_local_in_scope", "true"); - } - if (node->is_CallJava() && node->as_CallJava()->arg_escape()) { - print_prop("arg_escape", "true"); - } - if (node->is_Initialize() && node->as_Initialize()->does_not_escape()) { - print_prop("does_not_escape", "true"); - } + print_node.print_node_details(node); const char *short_name = "short_name"; if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { From d6943c532eeade593b17c7f14c136c20a3741e05 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 9 Mar 2026 09:10:41 +0000 Subject: [PATCH 107/170] 8379193: Incorrect build ID path in SATestUtils.java Reviewed-by: kevinw, ysuenaga --- test/lib/jdk/test/lib/SA/SATestUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/jdk/test/lib/SA/SATestUtils.java b/test/lib/jdk/test/lib/SA/SATestUtils.java index 50f5d71f1f1..754ef4c40dd 100644 --- a/test/lib/jdk/test/lib/SA/SATestUtils.java +++ b/test/lib/jdk/test/lib/SA/SATestUtils.java @@ -333,7 +333,7 @@ public class SATestUtils { .get(); String dir = buildID.substring(0, 2); String file = buildID.substring(2); - debuginfoPath = Path.of("/usr/lib/debug/.build_id", dir, file + ".debug"); + debuginfoPath = Path.of("/usr/lib/debug/.build-id", dir, file + ".debug"); exists = Files.exists(debuginfoPath); } catch (NoSuchElementException _) { // return null if vDSO not found. From 7101a0507c48d22762c20df4dbff88b180fc0f74 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Mon, 9 Mar 2026 09:14:56 +0000 Subject: [PATCH 108/170] 8379404: G1: Hide ConcurrentMarkThread reference from outside ConcurrentMark Reviewed-by: stefank, iwalulya --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 20 ++++---------- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 3 --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 28 +++++++++++++++++--- src/hotspot/share/gc/g1/g1ConcurrentMark.hpp | 17 +++++++++--- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 3f5d674c443..abc45254782 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1652,21 +1652,13 @@ jint G1CollectedHeap::initialize() { return JNI_OK; } -bool G1CollectedHeap::concurrent_mark_is_terminating() const { - assert(_cm != nullptr, "_cm must have been created"); - assert(_cm->is_fully_initialized(), "thread must exist in order to check if mark is terminating"); - return _cm->cm_thread()->should_terminate(); -} - void G1CollectedHeap::stop() { // Stop all concurrent threads. We do this to make sure these threads // do not continue to execute and access resources (e.g. logging) // that are destroyed during shutdown. _cr->stop(); _service_thread->stop(); - if (_cm->is_fully_initialized()) { - _cm->cm_thread()->stop(); - } + _cm->stop(); } void G1CollectedHeap::safepoint_synchronize_begin() { @@ -1857,12 +1849,12 @@ void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent, record_whole_heap_examined_timestamp(); } - // We need to clear the "in_progress" flag in the CM thread before + // We need to tell G1ConcurrentMark to update the state before // we wake up any waiters (especially when ExplicitInvokesConcurrent // is set) so that if a waiter requests another System.gc() it doesn't // incorrectly see that a marking cycle is still in progress. if (concurrent) { - _cm->cm_thread()->set_idle(); + _cm->notify_concurrent_cycle_completed(); } // Notify threads waiting in System.gc() (with ExplicitGCInvokesConcurrent) @@ -2565,11 +2557,9 @@ void G1CollectedHeap::start_concurrent_cycle(bool concurrent_operation_is_full_m assert(!_cm->in_progress(), "Can not start concurrent operation while in progress"); MutexLocker x(G1CGC_lock, Mutex::_no_safepoint_check_flag); if (concurrent_operation_is_full_mark) { - _cm->post_concurrent_mark_start(); - _cm->cm_thread()->start_full_mark(); + _cm->start_full_concurrent_cycle(); } else { - _cm->post_concurrent_undo_start(); - _cm->cm_thread()->start_undo_mark(); + _cm->start_undo_concurrent_cycle(); } G1CGC_lock->notify(); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 8ff9d481000..7a4cde9001e 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -915,9 +915,6 @@ public: // specified by the policy object. jint initialize() override; - // Returns whether concurrent mark threads (and the VM) are about to terminate. - bool concurrent_mark_is_terminating() const; - void safepoint_synchronize_begin() override; void safepoint_synchronize_end() override; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 074231a02d4..b4a5d673fd2 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -581,6 +581,11 @@ PartialArrayStateManager* G1ConcurrentMark::partial_array_state_manager() const return _partial_array_state_manager; } +G1ConcurrentMarkThread* G1ConcurrentMark::cm_thread() const { + assert(is_fully_initialized(), "must be"); + return _cm_thread; +} + void G1ConcurrentMark::reset() { _has_aborted.store_relaxed(false); @@ -715,7 +720,6 @@ public: private: // Heap region closure used for clearing the _mark_bitmap. class G1ClearBitmapHRClosure : public G1HeapRegionClosure { - private: G1ConcurrentMark* _cm; G1CMBitMap* _bitmap; bool _suspendible; // If suspendible, do yield checks. @@ -959,7 +963,7 @@ void G1ConcurrentMark::pre_concurrent_start(GCCause::Cause cause) { _gc_tracer_cm->set_gc_cause(cause); } -void G1ConcurrentMark::post_concurrent_mark_start() { +void G1ConcurrentMark::start_full_concurrent_cycle() { // Start Concurrent Marking weak-reference discovery. ReferenceProcessor* rp = _g1h->ref_processor_cm(); rp->start_discovery(false /* always_clear */); @@ -976,10 +980,26 @@ void G1ConcurrentMark::post_concurrent_mark_start() { // when marking is on. So, it's also called at the end of the // concurrent start pause to update the heap end, if the heap expands // during it. No need to call it here. + + // Signal the thread to start work. + cm_thread()->start_full_mark(); } -void G1ConcurrentMark::post_concurrent_undo_start() { +void G1ConcurrentMark::start_undo_concurrent_cycle() { root_regions()->cancel_scan(); + + // Signal the thread to start work. + cm_thread()->start_undo_mark(); +} + +void G1ConcurrentMark::notify_concurrent_cycle_completed() { + cm_thread()->set_idle(); +} + +void G1ConcurrentMark::stop() { + if (is_fully_initialized()) { + cm_thread()->stop(); + } } /* @@ -1943,7 +1963,7 @@ bool G1ConcurrentMark::concurrent_cycle_abort() { // has been signalled is already rare), and this work should be negligible compared // to actual full gc work. - if (!is_fully_initialized() || (!cm_thread()->in_progress() && !_g1h->concurrent_mark_is_terminating())) { + if (!is_fully_initialized() || (!cm_thread()->in_progress() && !cm_thread()->should_terminate())) { return false; } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index 11da6dae5b3..8bd04437097 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -352,6 +352,7 @@ class G1ConcurrentMark : public CHeapObj { friend class G1CMRemarkTask; friend class G1CMRootRegionScanTask; friend class G1CMTask; + friend class G1ClearBitMapTask; friend class G1ConcurrentMarkThread; G1ConcurrentMarkThread* _cm_thread; // The thread doing the work @@ -524,6 +525,9 @@ class G1ConcurrentMark : public CHeapObj { Atomic* _top_at_rebuild_starts; // True when Remark pause selected regions for rebuilding. bool _needs_remembered_set_rebuild; + + G1ConcurrentMarkThread* cm_thread() const; + public: // To be called when an object is marked the first time, e.g. after a successful // mark_in_bitmap call. Updates various statistics data. @@ -602,8 +606,6 @@ public: G1RegionToSpaceMapper* bitmap_storage); ~G1ConcurrentMark(); - G1ConcurrentMarkThread* cm_thread() { return _cm_thread; } - G1CMBitMap* mark_bitmap() const { return (G1CMBitMap*)&_mark_bitmap; } // Calculates the number of concurrent GC threads to be used in the marking phase. @@ -632,8 +634,15 @@ public: // These two methods do the work that needs to be done at the start and end of the // concurrent start pause. void pre_concurrent_start(GCCause::Cause cause); - void post_concurrent_mark_start(); - void post_concurrent_undo_start(); + + // Start the particular type of concurrent cycle. After this call threads may be running. + void start_full_concurrent_cycle(); + void start_undo_concurrent_cycle(); + + void notify_concurrent_cycle_completed(); + + // Stop active components/the concurrent mark thread. + void stop(); // Scan all the root regions and mark everything reachable from // them. From 695b83346f807e9bc2700ab412f1133957073c48 Mon Sep 17 00:00:00 2001 From: Saranya Natarajan Date: Mon, 9 Mar 2026 09:19:28 +0000 Subject: [PATCH 109/170] 8377148: Remove obsolete functions Matcher::is_spillable_arg() and Matcher::interpreter_frame_pointer_reg() Reviewed-by: dfenacci, rcastanedalo, mdoerr, fyang, amitkumar, mbaesken --- src/hotspot/cpu/aarch64/aarch64.ad | 18 +++--------------- src/hotspot/cpu/arm/arm.ad | 11 +++-------- src/hotspot/cpu/ppc/ppc.ad | 18 +++--------------- src/hotspot/cpu/riscv/riscv.ad | 18 +++--------------- src/hotspot/cpu/s390/s390.ad | 20 ++++---------------- src/hotspot/cpu/x86/x86.ad | 16 ++-------------- src/hotspot/share/adlc/adlparse.cpp | 10 +--------- src/hotspot/share/adlc/adlparse.hpp | 3 +-- src/hotspot/share/adlc/formsopt.cpp | 3 +-- src/hotspot/share/adlc/formsopt.hpp | 3 +-- src/hotspot/share/adlc/output_c.cpp | 10 +--------- src/hotspot/share/opto/matcher.hpp | 9 +++------ 12 files changed, 26 insertions(+), 113 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 9734c6845ea..51bb15e0f59 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, 2024, Red Hat, Inc. All rights reserved. // Copyright 2025 Arm Limited and/or its affiliates. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -2467,11 +2467,8 @@ bool Matcher::is_generic_vector(MachOper* opnd) { return opnd->opcode() == VREG; } +#ifdef ASSERT // Return whether or not this register is ever used as an argument. -// This function is used on startup to build the trampoline stubs in -// generateOptoStub. Registers not mentioned will be killed by the VM -// call in the trampoline, and arguments in those registers not be -// available to the callee. bool Matcher::can_be_java_arg(int reg) { return @@ -2492,11 +2489,7 @@ bool Matcher::can_be_java_arg(int reg) reg == V6_num || reg == V6_H_num || reg == V7_num || reg == V7_H_num; } - -bool Matcher::is_spillable_arg(int reg) -{ - return can_be_java_arg(reg); -} +#endif uint Matcher::int_pressure_limit() { @@ -3814,11 +3807,6 @@ frame %{ // Compiled code's Frame Pointer frame_pointer(R31); - // Interpreter stores its frame pointer in a register which is - // stored to the stack by I2CAdaptors. - // I2CAdaptors convert from interpreted java to compiled java. - interpreter_frame_pointer(R29); - // Stack alignment requirement stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes) diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 606275d7666..87c609be5a7 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1088,10 +1088,8 @@ bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, return clone_base_plus_offset_address(m, mstack, address_visited); } -// Return whether or not this register is ever used as an argument. This -// function is used on startup to build the trampoline stubs in generateOptoStub. -// Registers not mentioned will be killed by the VM call in the trampoline, and -// arguments in those registers not be available to the callee. +#ifdef ASSERT +// Return whether or not this register is ever used as an argument. bool Matcher::can_be_java_arg( int reg ) { if (reg == R_R0_num || reg == R_R1_num || @@ -1102,10 +1100,7 @@ bool Matcher::can_be_java_arg( int reg ) { reg <= R_S13_num) return true; return false; } - -bool Matcher::is_spillable_arg( int reg ) { - return can_be_java_arg(reg); -} +#endif uint Matcher::int_pressure_limit() { diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 4cb9f8820a0..7e3cd04171d 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2412,10 +2412,8 @@ bool Matcher::is_generic_vector(MachOper* opnd) { return false; } -// Return whether or not this register is ever used as an argument. This -// function is used on startup to build the trampoline stubs in generateOptoStub. -// Registers not mentioned will be killed by the VM call in the trampoline, and -// arguments in those registers not be available to the callee. +#ifdef ASSERT +// Return whether or not this register is ever used as an argument. bool Matcher::can_be_java_arg(int reg) { // We must include the virtual halves in order to get STDs and LDs // instead of STWs and LWs in the trampoline stubs. @@ -2447,10 +2445,7 @@ bool Matcher::can_be_java_arg(int reg) { return false; } - -bool Matcher::is_spillable_arg(int reg) { - return can_be_java_arg(reg); -} +#endif uint Matcher::int_pressure_limit() { @@ -3715,13 +3710,6 @@ frame %{ // Compiled code's Frame Pointer. frame_pointer(R1); // R1_SP - // Interpreter stores its frame pointer in a register which is - // stored to the stack by I2CAdaptors. I2CAdaptors convert from - // interpreted java to compiled java. - // - // R14_state holds pointer to caller's cInterpreter. - interpreter_frame_pointer(R14); // R14_state - stack_alignment(frame::alignment_in_bytes); // Number of outgoing stack slots killed above the diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index ed6e8db0606..54ea81683fc 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. // Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -2060,11 +2060,8 @@ bool Matcher::is_generic_vector(MachOper* opnd) { return false; } +#ifdef ASSERT // Return whether or not this register is ever used as an argument. -// This function is used on startup to build the trampoline stubs in -// generateOptoStub. Registers not mentioned will be killed by the VM -// call in the trampoline, and arguments in those registers not be -// available to the callee. bool Matcher::can_be_java_arg(int reg) { return @@ -2085,11 +2082,7 @@ bool Matcher::can_be_java_arg(int reg) reg == F16_num || reg == F16_H_num || reg == F17_num || reg == F17_H_num; } - -bool Matcher::is_spillable_arg(int reg) -{ - return can_be_java_arg(reg); -} +#endif uint Matcher::int_pressure_limit() { @@ -2559,11 +2552,6 @@ frame %{ // Compiled code's Frame Pointer frame_pointer(R2); - // Interpreter stores its frame pointer in a register which is - // stored to the stack by I2CAdaptors. - // I2CAdaptors convert from interpreted java to compiled java. - interpreter_frame_pointer(R8); - // Stack alignment requirement stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes) diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 19bd3620228..1521edde40c 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2017, 2024 SAP SE. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -1890,10 +1890,8 @@ const int z_num_iarg_registers = sizeof(z_iarg_reg) / sizeof(z_iarg_reg[0]); const int z_num_farg_registers = sizeof(z_farg_reg) / sizeof(z_farg_reg[0]); -// Return whether or not this register is ever used as an argument. This -// function is used on startup to build the trampoline stubs in generateOptoStub. -// Registers not mentioned will be killed by the VM call in the trampoline, and -// arguments in those registers not be available to the callee. +#ifdef ASSERT +// Return whether or not this register is ever used as an argument. bool Matcher::can_be_java_arg(int reg) { // We return true for all registers contained in z_iarg_reg[] and // z_farg_reg[] and their virtual halves. @@ -1917,10 +1915,7 @@ bool Matcher::can_be_java_arg(int reg) { return false; } - -bool Matcher::is_spillable_arg(int reg) { - return can_be_java_arg(reg); -} +#endif uint Matcher::int_pressure_limit() { @@ -2606,13 +2601,6 @@ frame %{ // z/Architecture stack pointer frame_pointer(Z_R15); // Z_SP - // Interpreter stores its frame pointer in a register which is - // stored to the stack by I2CAdaptors. I2CAdaptors convert from - // interpreted java to compiled java. - // - // Z_state holds pointer to caller's cInterpreter. - interpreter_frame_pointer(Z_R7); // Z_state - // Use alignment_in_bytes instead of log_2_of_alignment_in_bits. stack_alignment(frame::alignment_in_bytes); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index b155355c827..ed380105565 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2726,11 +2726,8 @@ bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { return (-128 <= offset && offset <= 127); } +#ifdef ASSERT // Return whether or not this register is ever used as an argument. -// This function is used on startup to build the trampoline stubs in -// generateOptoStub. Registers not mentioned will be killed by the VM -// call in the trampoline, and arguments in those registers not be -// available to the callee. bool Matcher::can_be_java_arg(int reg) { return @@ -2750,11 +2747,7 @@ bool Matcher::can_be_java_arg(int reg) reg == XMM6_num || reg == XMM6b_num || reg == XMM7_num || reg == XMM7b_num; } - -bool Matcher::is_spillable_arg(int reg) -{ - return can_be_java_arg(reg); -} +#endif uint Matcher::int_pressure_limit() { @@ -4691,11 +4684,6 @@ frame // Compiled code's Frame Pointer frame_pointer(RSP); - // Interpreter stores its frame pointer in a register which is - // stored to the stack by I2CAdaptors. - // I2CAdaptors convert from interpreted java to compiled java. - interpreter_frame_pointer(RBP); - // Stack alignment requirement stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes) diff --git a/src/hotspot/share/adlc/adlparse.cpp b/src/hotspot/share/adlc/adlparse.cpp index 356c24760e8..b49efa34be8 100644 --- a/src/hotspot/share/adlc/adlparse.cpp +++ b/src/hotspot/share/adlc/adlparse.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -993,9 +993,6 @@ void ADLParser::frame_parse(void) { if (strcmp(token,"frame_pointer")==0) { frame_pointer_parse(frame, false); } - if (strcmp(token,"interpreter_frame_pointer")==0) { - interpreter_frame_pointer_parse(frame, false); - } if (strcmp(token,"inline_cache_reg")==0) { inline_cache_parse(frame, false); } @@ -1119,11 +1116,6 @@ void ADLParser::frame_pointer_parse(FrameForm *frame, bool native) { else { frame->_frame_pointer = frame_pointer; } } -//------------------------------interpreter_frame_pointer_parse---------------------------- -void ADLParser::interpreter_frame_pointer_parse(FrameForm *frame, bool native) { - frame->_interpreter_frame_pointer_reg = parse_one_arg("interpreter frame pointer entry"); -} - //------------------------------inline_cache_parse----------------------------- void ADLParser::inline_cache_parse(FrameForm *frame, bool native) { frame->_inline_cache_reg = parse_one_arg("inline cache reg entry"); diff --git a/src/hotspot/share/adlc/adlparse.hpp b/src/hotspot/share/adlc/adlparse.hpp index 02baec53262..89296193612 100644 --- a/src/hotspot/share/adlc/adlparse.hpp +++ b/src/hotspot/share/adlc/adlparse.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,7 +120,6 @@ protected: // Parse the components of the frame section void sync_stack_slots_parse(FrameForm *frame); void frame_pointer_parse(FrameForm *frame, bool native); - void interpreter_frame_pointer_parse(FrameForm *frame, bool native); void inline_cache_parse(FrameForm *frame, bool native); void interpreter_arg_ptr_parse(FrameForm *frame, bool native); void interpreter_method_parse(FrameForm *frame, bool native); diff --git a/src/hotspot/share/adlc/formsopt.cpp b/src/hotspot/share/adlc/formsopt.cpp index fbd1043492e..091e34f40f4 100644 --- a/src/hotspot/share/adlc/formsopt.cpp +++ b/src/hotspot/share/adlc/formsopt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -476,7 +476,6 @@ void AllocClass::forms_do(FormClosure* f) { FrameForm::FrameForm() { _sync_stack_slots = nullptr; _inline_cache_reg = nullptr; - _interpreter_frame_pointer_reg = nullptr; _cisc_spilling_operand_name = nullptr; _frame_pointer = nullptr; _c_frame_pointer = nullptr; diff --git a/src/hotspot/share/adlc/formsopt.hpp b/src/hotspot/share/adlc/formsopt.hpp index 9e0c9db854d..087ab1e2653 100644 --- a/src/hotspot/share/adlc/formsopt.hpp +++ b/src/hotspot/share/adlc/formsopt.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -347,7 +347,6 @@ public: // Public Data char *_sync_stack_slots; char *_inline_cache_reg; - char *_interpreter_frame_pointer_reg; char *_cisc_spilling_operand_name; char *_frame_pointer; char *_c_frame_pointer; diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp index 9cbd6aaf66f..45b3d6bda63 100644 --- a/src/hotspot/share/adlc/output_c.cpp +++ b/src/hotspot/share/adlc/output_c.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -4212,14 +4212,6 @@ void ArchDesc::buildFrameMethods(FILE *fp_cpp) { fprintf(fp_cpp,"int Matcher::inline_cache_reg_encode() {"); fprintf(fp_cpp," return _regEncode[inline_cache_reg()]; }\n\n"); - // Interpreter's Frame Pointer Register - fprintf(fp_cpp,"OptoReg::Name Matcher::interpreter_frame_pointer_reg() {"); - if (_frame->_interpreter_frame_pointer_reg == nullptr) - fprintf(fp_cpp," return OptoReg::Bad; }\n\n"); - else - fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", - _frame->_interpreter_frame_pointer_reg); - // Frame Pointer definition /* CNC - I can not contemplate having a different frame pointer between Java and native code; makes my head hurt to think about it. diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 9579af84f24..69e5ab354f1 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -221,12 +221,12 @@ public: // Convert a machine register to a machine register type, so-as to // properly match spill code. const int *_register_save_type; + #ifdef ASSERT // Maps from machine register to boolean; true if machine register can // be holding a call argument in some signature. static bool can_be_java_arg( int reg ); - // Maps from machine register to boolean; true if machine register holds - // a spillable argument. - static bool is_spillable_arg( int reg ); + #endif + // Number of integer live ranges that constitute high register pressure static uint int_pressure_limit(); // Number of float live ranges that constitute high register pressure @@ -443,9 +443,6 @@ public: // The Method-klass-holder may be passed in the inline_cache_reg // and then expanded into the inline_cache_reg and a method_ptr register - // Interpreter's Frame Pointer Register - static OptoReg::Name interpreter_frame_pointer_reg(); - // Java-Native calling convention // (what you use when intercalling between Java and C++ code) From 996033a601bd89712a447cdbfefd854c59083edc Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Mon, 9 Mar 2026 09:45:59 +0000 Subject: [PATCH 110/170] 8378625: C2: Refactor MemNode::detect_access_independence to a separate method Reviewed-by: mhaessig, chagedorn, aseoane --- src/hotspot/share/opto/memnode.cpp | 361 +++++++++++++++-------------- src/hotspot/share/opto/memnode.hpp | 42 ++++ 2 files changed, 233 insertions(+), 170 deletions(-) diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 21ed15f9ec7..f7da9a96d34 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -582,7 +582,6 @@ bool MemNode::detect_ptr_independence(Node* p1, AllocateNode* a1, return false; } - // Find an arraycopy ac that produces the memory state represented by parameter mem. // Return ac if // (a) can_see_stored_value=true and ac must have set the value for this load or if @@ -697,178 +696,32 @@ ArrayCopyNode* MemNode::find_array_copy_clone(Node* ld_alloc, Node* mem) const { // (Currently, only LoadNode::Ideal has steps (c), (d). More later.) // Node* MemNode::find_previous_store(PhaseValues* phase) { - Node* ctrl = in(MemNode::Control); - Node* adr = in(MemNode::Address); - intptr_t offset = 0; - Node* base = AddPNode::Ideal_base_and_offset(adr, phase, offset); - AllocateNode* alloc = AllocateNode::Ideal_allocation(base); + AccessAnalyzer analyzer(phase, this); - const TypePtr* adr_type = this->adr_type(); - if (adr_type == nullptr) { - // This means the access is dead - return phase->C->top(); - } else if (adr_type->base() == TypePtr::AnyPtr) { - assert(adr_type->ptr() == TypePtr::Null, "MemNode should never access a wide memory"); - // Give up, this will upset Compile::get_alias_index - return nullptr; - } - - int alias_idx = phase->C->get_alias_index(adr_type); - assert(alias_idx != Compile::AliasIdxTop, "must not be a dead node"); - assert(alias_idx != Compile::AliasIdxBot || !phase->C->do_aliasing(), "must not be a very wide access"); - - if (offset == Type::OffsetBot) - return nullptr; // cannot unalias unless there are precise offsets - - const bool adr_maybe_raw = check_if_adr_maybe_raw(adr); - const TypeOopPtr *addr_t = adr->bottom_type()->isa_oopptr(); - - intptr_t size_in_bytes = memory_size(); - - Node* mem = in(MemNode::Memory); // start searching here... - - int cnt = 50; // Cycle limiter - for (;;) { // While we can dance past unrelated stores... - if (--cnt < 0) break; // Caught in cycle or a complicated dance? - - Node* prev = mem; - if (mem->is_Store()) { - Node* st_adr = mem->in(MemNode::Address); - intptr_t st_offset = 0; - Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_offset); - if (st_base == nullptr) { - // inscrutable pointer - break; - } - - // If the bases are the same and the offsets are the same, it seems that this is the exact - // store we are looking for, the caller will check if the type of the store matches using - // MemNode::can_see_stored_value - if (st_base == base && st_offset == offset) { - return mem; // (b) found the store that this access observes - } - - // If it is provable that the memory accessed by mem does not overlap the memory accessed by - // this, we may walk past mem. - // For raw accesses, 2 accesses are independent if they have the same base and the offsets - // say that they do not overlap. - // For heap accesses, 2 accesses are independent if either the bases are provably different - // at runtime or the offsets say that the accesses do not overlap. - if ((adr_maybe_raw || check_if_adr_maybe_raw(st_adr)) && st_base != base) { - // Raw accesses can only be provably independent if they have the same base - break; - } - - // If the offsets say that the accesses do not overlap, then it is provable that mem and this - // do not overlap. For example, a LoadI from Object+8 is independent from a StoreL into - // Object+12, no matter what the bases are. - if (st_offset != offset && st_offset != Type::OffsetBot) { - const int MAX_STORE = MAX2(BytesPerLong, (int)MaxVectorSize); - assert(mem->as_Store()->memory_size() <= MAX_STORE, ""); - if (st_offset >= offset + size_in_bytes || - st_offset <= offset - MAX_STORE || - st_offset <= offset - mem->as_Store()->memory_size()) { - // Success: The offsets are provably independent. - // (You may ask, why not just test st_offset != offset and be done? - // The answer is that stores of different sizes can co-exist - // in the same sequence of RawMem effects. We sometimes initialize - // a whole 'tile' of array elements with a single jint or jlong.) - mem = mem->in(MemNode::Memory); - continue; // (a) advance through the independent store - } - } - - // Same base and overlapping offsets, it seems provable that the accesses overlap, give up - if (st_base == base) { - break; - } - - // Try to prove that 2 different base nodes at compile time are different values at runtime - bool known_independent = false; - if (detect_ptr_independence(base, alloc, st_base, AllocateNode::Ideal_allocation(st_base), phase)) { - known_independent = true; - } - - if (known_independent) { - mem = mem->in(MemNode::Memory); - continue; // (a) advance through the independent store - } - } else if (mem->is_Proj() && mem->in(0)->is_Initialize()) { - InitializeNode* st_init = mem->in(0)->as_Initialize(); - AllocateNode* st_alloc = st_init->allocation(); - if (st_alloc == nullptr) { - break; // something degenerated - } - bool known_identical = false; - bool known_independent = false; - if (alloc == st_alloc) { - known_identical = true; - } else if (alloc != nullptr) { - known_independent = true; - } else if (all_controls_dominate(this, st_alloc)) { - known_independent = true; - } - - if (known_independent) { - // The bases are provably independent: Either they are - // manifestly distinct allocations, or else the control - // of this load dominates the store's allocation. - if (alias_idx == Compile::AliasIdxRaw) { - mem = st_alloc->in(TypeFunc::Memory); - } else { - mem = st_init->memory(alias_idx); - } - continue; // (a) advance through independent store memory - } - - // (b) at this point, if we are not looking at a store initializing - // the same allocation we are loading from, we lose. - if (known_identical) { - // From caller, can_see_stored_value will consult find_captured_store. - return mem; // let caller handle steps (c), (d) - } - - } else if (find_previous_arraycopy(phase, alloc, mem, false) != nullptr) { - if (prev != mem) { - // Found an arraycopy but it doesn't affect that load - continue; - } - // Found an arraycopy that may affect that load - return mem; - } else if (mem->is_MergeMem()) { - mem = mem->as_MergeMem()->memory_at(alias_idx); - continue; - } else if (addr_t != nullptr && addr_t->is_known_instance_field()) { - // Can't use optimize_simple_memory_chain() since it needs PhaseGVN. - if (mem->is_Proj() && mem->in(0)->is_Call()) { - // ArrayCopyNodes processed here as well. - CallNode *call = mem->in(0)->as_Call(); - if (!call->may_modify(addr_t, phase)) { - mem = call->in(TypeFunc::Memory); - continue; // (a) advance through independent call memory - } - } else if (mem->is_Proj() && mem->in(0)->is_MemBar()) { - ArrayCopyNode* ac = nullptr; - if (ArrayCopyNode::may_modify(addr_t, mem->in(0)->as_MemBar(), phase, ac)) { - break; - } - mem = mem->in(0)->in(TypeFunc::Memory); - continue; // (a) advance through independent MemBar memory - } else if (mem->is_ClearArray()) { - if (ClearArrayNode::step_through(&mem, (uint)addr_t->instance_id(), phase)) { - // (the call updated 'mem' value) - continue; // (a) advance through independent allocation memory - } else { - // Can not bypass initialization of the instance - // we are looking for. - return mem; - } - } + Node* mem = in(MemNode::Memory); // start searching here... + int cnt = 50; // Cycle limiter + for (;; cnt--) { + // While we can dance past unrelated stores... + if (phase->type(mem) == Type::TOP) { + // Encounter a dead node + return phase->C->top(); + } else if (cnt <= 0) { + // Caught in cycle or a complicated dance? + return nullptr; + } else if (mem->is_Phi()) { + return nullptr; } - // Unless there is an explicit 'continue', we must bail out here, - // because 'mem' is an inscrutable memory state (e.g., a call). - break; + AccessAnalyzer::AccessIndependence independence = analyzer.detect_access_independence(mem); + if (independence.independent) { + // (a) advance through the independent store + mem = independence.mem; + assert(mem != nullptr, "must not be nullptr"); + } else { + // (b) found the store that this access observes if this is not null + // Otherwise, give up if it is null + return independence.mem; + } } return nullptr; // bail out @@ -918,6 +771,174 @@ uint8_t MemNode::barrier_data(const Node* n) { return 0; } +AccessAnalyzer::AccessAnalyzer(PhaseValues* phase, MemNode* n) + : _phase(phase), _n(n), _memory_size(n->memory_size()), _alias_idx(-1) { + Node* adr = _n->in(MemNode::Address); + _offset = 0; + _base = AddPNode::Ideal_base_and_offset(adr, _phase, _offset); + _maybe_raw = MemNode::check_if_adr_maybe_raw(adr); + _alloc = AllocateNode::Ideal_allocation(_base); + _adr_type = _n->adr_type(); + + if (_adr_type != nullptr && _adr_type->base() != TypePtr::AnyPtr) { + // Avoid the cases that will upset Compile::get_alias_index + _alias_idx = _phase->C->get_alias_index(_adr_type); + assert(_alias_idx != Compile::AliasIdxTop, "must not be a dead node"); + assert(_alias_idx != Compile::AliasIdxBot || !phase->C->do_aliasing(), "must not be a very wide access"); + } +} + +// Decide whether the memory accessed by '_n' and 'other' may overlap. This function may be used +// when we want to walk the memory graph to fold a load, or when we want to hoist a load above a +// loop when there are no stores that may overlap with the load inside the loop. +AccessAnalyzer::AccessIndependence AccessAnalyzer::detect_access_independence(Node* other) const { + assert(_phase->type(other) == Type::MEMORY, "must be a memory node %s", other->Name()); + assert(!other->is_Phi(), "caller must handle Phi"); + + if (_adr_type == nullptr) { + // This means the access is dead + return {false, _phase->C->top()}; + } else if (_adr_type->base() == TypePtr::AnyPtr) { + // An example for this case is an access into the memory address 0 performed using Unsafe + assert(_adr_type->ptr() == TypePtr::Null, "MemNode should never access a wide memory"); + return {false, nullptr}; + } + + if (_offset == Type::OffsetBot) { + // cannot unalias unless there are precise offsets + return {false, nullptr}; + } + + const TypeOopPtr* adr_oop_type = _adr_type->isa_oopptr(); + Node* prev = other; + if (other->is_Store()) { + Node* st_adr = other->in(MemNode::Address); + intptr_t st_offset = 0; + Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, _phase, st_offset); + if (st_base == nullptr) { + // inscrutable pointer + return {false, nullptr}; + } + + // If the bases are the same and the offsets are the same, it seems that this is the exact + // store we are looking for, the caller will check if the type of the store matches using + // MemNode::can_see_stored_value + if (st_base == _base && st_offset == _offset) { + return {false, other}; + } + + // If it is provable that the memory accessed by 'other' does not overlap the memory accessed + // by '_n', we may walk past 'other'. + // For raw accesses, 2 accesses are independent if they have the same base and the offsets + // say that they do not overlap. + // For heap accesses, 2 accesses are independent if either the bases are provably different + // at runtime or the offsets say that the accesses do not overlap. + if ((_maybe_raw || MemNode::check_if_adr_maybe_raw(st_adr)) && st_base != _base) { + // Raw accesses can only be provably independent if they have the same base + return {false, nullptr}; + } + + // If the offsets say that the accesses do not overlap, then it is provable that 'other' and + // '_n' do not overlap. For example, a LoadI from Object+8 is independent from a StoreL into + // Object+12, no matter what the bases are. + if (st_offset != _offset && st_offset != Type::OffsetBot) { + const int MAX_STORE = MAX2(BytesPerLong, (int)MaxVectorSize); + assert(other->as_Store()->memory_size() <= MAX_STORE, ""); + if (st_offset >= _offset + _memory_size || + st_offset <= _offset - MAX_STORE || + st_offset <= _offset - other->as_Store()->memory_size()) { + // Success: The offsets are provably independent. + // (You may ask, why not just test st_offset != offset and be done? + // The answer is that stores of different sizes can co-exist + // in the same sequence of RawMem effects. We sometimes initialize + // a whole 'tile' of array elements with a single jint or jlong.) + return {true, other->in(MemNode::Memory)}; + } + } + + // Same base and overlapping offsets, it seems provable that the accesses overlap, give up + if (st_base == _base) { + return {false, nullptr}; + } + + // Try to prove that 2 different base nodes at compile time are different values at runtime + bool known_independent = false; + if (MemNode::detect_ptr_independence(_base, _alloc, st_base, AllocateNode::Ideal_allocation(st_base), _phase)) { + known_independent = true; + } + + if (known_independent) { + return {true, other->in(MemNode::Memory)}; + } + } else if (other->is_Proj() && other->in(0)->is_Initialize()) { + InitializeNode* st_init = other->in(0)->as_Initialize(); + AllocateNode* st_alloc = st_init->allocation(); + if (st_alloc == nullptr) { + // Something degenerated + return {false, nullptr}; + } + bool known_identical = false; + bool known_independent = false; + if (_alloc == st_alloc) { + known_identical = true; + } else if (_alloc != nullptr) { + known_independent = true; + } else if (MemNode::all_controls_dominate(_n, st_alloc)) { + known_independent = true; + } + + if (known_independent) { + // The bases are provably independent: Either they are + // manifestly distinct allocations, or else the control + // of _n dominates the store's allocation. + if (_alias_idx == Compile::AliasIdxRaw) { + other = st_alloc->in(TypeFunc::Memory); + } else { + other = st_init->memory(_alias_idx); + } + return {true, other}; + } + + // If we are not looking at a store initializing the same + // allocation we are loading from, we lose. + if (known_identical) { + // From caller, can_see_stored_value will consult find_captured_store. + return {false, other}; + } + + } else if (_n->find_previous_arraycopy(_phase, _alloc, other, false) != nullptr) { + // Find an arraycopy that may or may not affect the MemNode + return {prev != other, other}; + } else if (other->is_MergeMem()) { + return {true, other->as_MergeMem()->memory_at(_alias_idx)}; + } else if (adr_oop_type != nullptr && adr_oop_type->is_known_instance_field()) { + // Can't use optimize_simple_memory_chain() since it needs PhaseGVN. + if (other->is_Proj() && other->in(0)->is_Call()) { + // ArrayCopyNodes processed here as well. + CallNode* call = other->in(0)->as_Call(); + if (!call->may_modify(adr_oop_type, _phase)) { + return {true, call->in(TypeFunc::Memory)}; + } + } else if (other->is_Proj() && other->in(0)->is_MemBar()) { + ArrayCopyNode* ac = nullptr; + if (!ArrayCopyNode::may_modify(adr_oop_type, other->in(0)->as_MemBar(), _phase, ac)) { + return {true, other->in(0)->in(TypeFunc::Memory)}; + } + } else if (other->is_ClearArray()) { + if (ClearArrayNode::step_through(&other, (uint)adr_oop_type->instance_id(), _phase)) { + // (the call updated 'other' value) + return {true, other}; + } else { + // Can not bypass initialization of the instance + // we are looking for. + return {false, other}; + } + } + } + + return {false, nullptr}; +} + //============================================================================= // Should LoadNode::Ideal() attempt to remove control edges? bool LoadNode::can_remove_control() const { diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index 39b1ee88333..2f26c67f0a8 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -26,6 +26,7 @@ #ifndef SHARE_OPTO_MEMNODE_HPP #define SHARE_OPTO_MEMNODE_HPP +#include "memory/allocation.hpp" #include "opto/multnode.hpp" #include "opto/node.hpp" #include "opto/opcodes.hpp" @@ -46,6 +47,8 @@ private: bool _unsafe_access; // Access of unsafe origin. uint8_t _barrier_data; // Bit field with barrier information + friend class AccessAnalyzer; + protected: #ifdef ASSERT const TypePtr* _adr_type; // What kind of memory is being addressed? @@ -172,6 +175,45 @@ public: #endif }; +// Analyze a MemNode to try to prove that it is independent from other memory accesses +class AccessAnalyzer : StackObj { +private: + PhaseValues* const _phase; + MemNode* const _n; + Node* _base; + intptr_t _offset; + const int _memory_size; + bool _maybe_raw; + AllocateNode* _alloc; + const TypePtr* _adr_type; + int _alias_idx; + +public: + AccessAnalyzer(PhaseValues* phase, MemNode* n); + + // The result of deciding whether a memory node 'other' writes into the memory which '_n' + // observes. + class AccessIndependence { + public: + // Whether 'other' writes into the memory which '_n' observes. This value is conservative, that + // is, it is only true when it is provable that the memory accessed by the nodes is + // non-overlapping. + bool independent; + + // If 'independent' is true, this is the memory input of 'other' that corresponds to the memory + // location that '_n' observes. For example, if 'other' is a StoreNode, then 'mem' is its + // memory input, if 'other' is a MergeMemNode, then 'mem' is the memory input corresponding to + // the alias class of '_n'. + // If 'independent' is false, + // - 'mem' is non-nullptr if it seems that 'other' writes to the exact memory location '_n' + // observes. + // - 'mem' is nullptr otherwise. + Node* mem; + }; + + AccessIndependence detect_access_independence(Node* other) const; +}; + //------------------------------LoadNode--------------------------------------- // Load value; requires Memory and Address class LoadNode : public MemNode { From f1be8208c8330c3d1ca745c92c91528ae8fa68fd Mon Sep 17 00:00:00 2001 From: Raffaello Giulietti Date: Mon, 9 Mar 2026 09:53:47 +0000 Subject: [PATCH 111/170] 8379195: Refactor Arrays TestNG tests to use JUnit Reviewed-by: alanb --- .../jdk/java/util/Arrays/ArraysEqCmpTest.java | 133 ++++++++++-------- test/jdk/java/util/Arrays/AsList.java | 45 +++--- test/jdk/java/util/Arrays/Correct.java | 22 +-- test/jdk/java/util/Arrays/SetAllTest.java | 47 ++++--- .../Arrays/SortingNearlySortedPrimitive.java | 16 ++- .../util/Arrays/StreamAndSpliterator.java | 17 ++- test/jdk/java/util/Arrays/TEST.properties | 1 + .../Arrays/largeMemory/ParallelPrefix.java | 76 +++++----- 8 files changed, 182 insertions(+), 175 deletions(-) create mode 100644 test/jdk/java/util/Arrays/TEST.properties diff --git a/test/jdk/java/util/Arrays/ArraysEqCmpTest.java b/test/jdk/java/util/Arrays/ArraysEqCmpTest.java index a2bb9ce6a79..5e987746771 100644 --- a/test/jdk/java/util/Arrays/ArraysEqCmpTest.java +++ b/test/jdk/java/util/Arrays/ArraysEqCmpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,9 @@ * @test * @bug 8033148 8141409 * @summary tests for array equals and compare - * @run testng ArraysEqCmpTest + * @run junit ArraysEqCmpTest */ -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -46,6 +43,13 @@ import java.util.function.BiFunction; import java.util.function.LongFunction; import java.util.stream.IntStream; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ArraysEqCmpTest { // Maximum width in bits @@ -588,7 +592,6 @@ public class ArraysEqCmpTest { static Object[][] arrayTypes; - @DataProvider public static Object[][] arrayTypesProvider() { if (arrayTypes == null) { arrayTypes = new Object[][]{ @@ -613,7 +616,6 @@ public class ArraysEqCmpTest { static Object[][] floatArrayTypes; - @DataProvider public static Object[][] floatArrayTypesProvider() { if (floatArrayTypes == null) { LongFunction bTof = rb -> Float.intBitsToFloat((int) rb); @@ -629,7 +631,6 @@ public class ArraysEqCmpTest { static Object[][] objectArrayTypes; - @DataProvider public static Object[][] objectArrayTypesProvider() { if (objectArrayTypes == null) { LongFunction bTof = rb -> Float.intBitsToFloat((int) rb); @@ -646,7 +647,6 @@ public class ArraysEqCmpTest { static Object[][] signedUnsignedArrayTypes; - @DataProvider public static Object[][] signedUnsignedArrayTypes() { if (signedUnsignedArrayTypes == null) { signedUnsignedArrayTypes = new Object[][]{ @@ -661,7 +661,8 @@ public class ArraysEqCmpTest { // Equality and comparison tests - @Test(dataProvider = "arrayTypesProvider") + @ParameterizedTest + @MethodSource("arrayTypesProvider") public void testArray(ArrayType arrayType) { BiFunction, Integer, Object> constructor = (at, s) -> { Object a = at.construct(s); @@ -677,7 +678,8 @@ public class ArraysEqCmpTest { testArrayType(arrayType, constructor, cloner); } - @Test(dataProvider = "floatArrayTypesProvider") + @ParameterizedTest + @MethodSource("floatArrayTypesProvider") public void testPrimitiveFloatArray( ArrayType arrayType, long canonicalNanRawBits, long nonCanonicalNanRawBits, @@ -722,7 +724,8 @@ public class ArraysEqCmpTest { testArrayType(arrayType, canonicalNaNs, halfNonCanonicalNaNs); } - @Test(dataProvider = "objectArrayTypesProvider") + @ParameterizedTest + @MethodSource("objectArrayTypesProvider") public void testNullElementsInObjectArray(ArrayType arrayType) { BiFunction, Object, Object> cloner = ArrayType::copyOf; @@ -752,11 +755,12 @@ public class ArraysEqCmpTest { Integer[] a = new Integer[]{null, 0}; Integer[] b = new Integer[]{0, 0}; - Assert.assertTrue(Arrays.compare(a, b) < 0); - Assert.assertTrue(Arrays.compare(b, a) > 0); + Assertions.assertTrue(Arrays.compare(a, b) < 0); + Assertions.assertTrue(Arrays.compare(b, a) > 0); } - @Test(dataProvider = "objectArrayTypesProvider") + @ParameterizedTest + @MethodSource("objectArrayTypesProvider") public void testSameRefElementsInObjectArray(ArrayType arrayType) { BiFunction, Object, Object> cloner = ArrayType::copyOf; @@ -796,7 +800,8 @@ public class ArraysEqCmpTest { cloner); } - @Test(dataProvider = "signedUnsignedArrayTypes") + @ParameterizedTest + @MethodSource("signedUnsignedArrayTypes") public void testSignedUnsignedArray(ArrayType sat, ArrayType uat) { BiFunction, Integer, Object> constructor = (at, s) -> { Object a = at.construct(s); @@ -824,8 +829,8 @@ public class ArraysEqCmpTest { int sc = sat.compare(ac, aFrom, aTo, a, aFrom, aTo); int uc = uat.compare(ac, aFrom, aTo, a, aFrom, aTo); - Assert.assertTrue(sc < 0); - Assert.assertTrue(uc > 0); + Assertions.assertTrue(sc < 0); + Assertions.assertTrue(uc > 0); } } } @@ -854,31 +859,31 @@ public class ArraysEqCmpTest { Object bnr = at.copyOf(b, bFrom, bTo); boolean eq = isEqual(at, a, aFrom, aTo, b, bFrom, bTo); - Assert.assertEquals(at.equals(a, aFrom, aTo, b, bFrom, bTo), eq); - Assert.assertEquals(at.equals(b, bFrom, bTo, a, aFrom, aTo), eq); - Assert.assertEquals(at.equals(anr, bnr), eq); - Assert.assertEquals(at.equals(bnr, anr), eq); + Assertions.assertEquals(eq, at.equals(a, aFrom, aTo, b, bFrom, bTo)); + Assertions.assertEquals(eq, at.equals(b, bFrom, bTo, a, aFrom, aTo)); + Assertions.assertEquals(eq, at.equals(anr, bnr)); + Assertions.assertEquals(eq, at.equals(bnr, anr)); if (eq) { - Assert.assertEquals(at.compare(a, aFrom, aTo, b, bFrom, bTo), 0); - Assert.assertEquals(at.compare(b, bFrom, bTo, a, aFrom, aTo), 0); - Assert.assertEquals(at.compare(anr, bnr), 0); - Assert.assertEquals(at.compare(bnr, anr), 0); + Assertions.assertEquals(0, at.compare(a, aFrom, aTo, b, bFrom, bTo)); + Assertions.assertEquals(0, at.compare(b, bFrom, bTo, a, aFrom, aTo)); + Assertions.assertEquals(0, at.compare(anr, bnr)); + Assertions.assertEquals(0, at.compare(bnr, anr)); - Assert.assertEquals(at.mismatch(a, aFrom, aTo, b, bFrom, bTo), -1); - Assert.assertEquals(at.mismatch(b, bFrom, bTo, a, aFrom, aTo), -1); - Assert.assertEquals(at.mismatch(anr, bnr), -1); - Assert.assertEquals(at.mismatch(bnr, anr), -1); + Assertions.assertEquals(-1, at.mismatch(a, aFrom, aTo, b, bFrom, bTo)); + Assertions.assertEquals(-1, at.mismatch(b, bFrom, bTo, a, aFrom, aTo)); + Assertions.assertEquals(-1, at.mismatch(anr, bnr)); + Assertions.assertEquals(-1, at.mismatch(bnr, anr)); } else { int aCb = at.compare(a, aFrom, aTo, b, bFrom, bTo); int bCa = at.compare(b, bFrom, bTo, a, aFrom, aTo); int v = Integer.signum(aCb) * Integer.signum(bCa); - Assert.assertTrue(v == -1); + Assertions.assertTrue(v == -1); int anrCbnr = at.compare(anr, bnr); int bnrCanr = at.compare(bnr, anr); - Assert.assertEquals(anrCbnr, aCb); - Assert.assertEquals(bnrCanr, bCa); + Assertions.assertEquals(aCb, anrCbnr); + Assertions.assertEquals(bCa, bnrCanr); int aMb = at.mismatch(a, aFrom, aTo, b, bFrom, bTo); @@ -886,18 +891,18 @@ public class ArraysEqCmpTest { int anrMbnr = at.mismatch(anr, bnr); int bnrManr = at.mismatch(bnr, anr); - Assert.assertNotEquals(aMb, -1); - Assert.assertEquals(aMb, bMa); - Assert.assertNotEquals(anrMbnr, -1); - Assert.assertEquals(anrMbnr, bnrManr); - Assert.assertEquals(aMb, anrMbnr); - Assert.assertEquals(bMa, bnrManr); + Assertions.assertNotEquals(-1, aMb); + Assertions.assertEquals(bMa, aMb); + Assertions.assertNotEquals(-1, anrMbnr); + Assertions.assertEquals(bnrManr, anrMbnr); + Assertions.assertEquals(anrMbnr, aMb); + Assertions.assertEquals(bnrManr, bMa); // Common or proper prefix - Assert.assertTrue(at.equals(a, aFrom, aFrom + aMb, b, bFrom, bFrom + aMb)); + Assertions.assertTrue(at.equals(a, aFrom, aFrom + aMb, b, bFrom, bFrom + aMb)); if (aMb < Math.min(aLength, bLength)) { // Common prefix - Assert.assertFalse(isEqual(at, a, aFrom + aMb, b, bFrom + aMb)); + Assertions.assertFalse(isEqual(at, a, aFrom + aMb, b, bFrom + aMb)); } } } @@ -912,29 +917,29 @@ public class ArraysEqCmpTest { Object acnr = at.copyOf(ac, aFrom, aTo); Object anr = at.copyOf(a, aFrom, aTo); - Assert.assertFalse(at.equals(ac, aFrom, aTo, a, aFrom, aTo)); - Assert.assertFalse(at.equals(acnr, anr)); + Assertions.assertFalse(at.equals(ac, aFrom, aTo, a, aFrom, aTo)); + Assertions.assertFalse(at.equals(acnr, anr)); int acCa = at.compare(ac, aFrom, aTo, a, aFrom, aTo); int aCac = at.compare(a, aFrom, aTo, ac, aFrom, aTo); int v = Integer.signum(acCa) * Integer.signum(aCac); - Assert.assertTrue(v == -1); + Assertions.assertTrue(v == -1); int acnrCanr = at.compare(acnr, anr); int anrCacnr = at.compare(anr, acnr); - Assert.assertEquals(acnrCanr, acCa); - Assert.assertEquals(anrCacnr, aCac); + Assertions.assertEquals(acCa, acnrCanr); + Assertions.assertEquals(aCac, anrCacnr); int acMa = at.mismatch(ac, aFrom, aTo, a, aFrom, aTo); int aMac = at.mismatch(a, aFrom, aTo, ac, aFrom, aTo); - Assert.assertEquals(acMa, aMac); - Assert.assertEquals(acMa, i - aFrom); + Assertions.assertEquals(aMac, acMa); + Assertions.assertEquals(i - aFrom, acMa); int acnrManr = at.mismatch(acnr, anr); int anrMacnr = at.mismatch(anr, acnr); - Assert.assertEquals(acnrManr, anrMacnr); - Assert.assertEquals(acnrManr, i - aFrom); + Assertions.assertEquals(anrMacnr, acnrManr); + Assertions.assertEquals(i - aFrom, acnrManr); } } } @@ -986,24 +991,26 @@ public class ArraysEqCmpTest { // Null array reference tests - @Test(dataProvider = "arrayTypesProvider") + @ParameterizedTest + @MethodSource("arrayTypesProvider") public void testNullArrayRefs(ArrayType arrayType) { Object n = null; Object a = arrayType.construct(0); - Assert.assertTrue(arrayType.equals(n, n)); - Assert.assertFalse(arrayType.equals(n, a)); - Assert.assertFalse(arrayType.equals(a, n)); + Assertions.assertTrue(arrayType.equals(n, n)); + Assertions.assertFalse(arrayType.equals(n, a)); + Assertions.assertFalse(arrayType.equals(a, n)); - Assert.assertEquals(arrayType.compare(n, n), 0); - Assert.assertTrue(arrayType.compare(n, a) < 0); - Assert.assertTrue(arrayType.compare(a, n) > 0); + Assertions.assertEquals(0, arrayType.compare(n, n)); + Assertions.assertTrue(arrayType.compare(n, a) < 0); + Assertions.assertTrue(arrayType.compare(a, n) > 0); } // Exception throwing tests - @Test(dataProvider = "arrayTypesProvider") + @ParameterizedTest + @MethodSource("arrayTypesProvider") public void testNPEs(ArrayType arrayType) { Object[] values = new Object[]{null, arrayType.construct(0)}; @@ -1046,7 +1053,8 @@ public class ArraysEqCmpTest { } } - @Test(dataProvider = "arrayTypesProvider") + @ParameterizedTest + @MethodSource("arrayTypesProvider") public void testIAEs(ArrayType arrayType) { List values = Arrays.asList(0, 1); @@ -1065,7 +1073,8 @@ public class ArraysEqCmpTest { } } - @Test(dataProvider = "arrayTypesProvider") + @ParameterizedTest + @MethodSource("arrayTypesProvider") public void testAIOBEs(ArrayType arrayType) { List froms = Arrays.asList(-1, 0); @@ -1110,7 +1119,7 @@ public class ArraysEqCmpTest { catch (Throwable t) { caught = t; } - Assert.assertNotNull(caught); - Assert.assertTrue(expected.isInstance(caught)); + Assertions.assertNotNull(caught); + Assertions.assertTrue(expected.isInstance(caught)); } } \ No newline at end of file diff --git a/test/jdk/java/util/Arrays/AsList.java b/test/jdk/java/util/Arrays/AsList.java index c64c473a822..b02f1dcbe68 100644 --- a/test/jdk/java/util/Arrays/AsList.java +++ b/test/jdk/java/util/Arrays/AsList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,11 @@ * questions. */ -/** +/* * @test * @bug 8155600 * @summary Tests for Arrays.asList() - * @run testng AsList + * @run junit AsList */ import java.util.Arrays; @@ -33,46 +33,35 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.stream.IntStream; -import org.testng.annotations.Test; -import org.testng.annotations.DataProvider; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.fail; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class AsList { /* * Iterator contract test */ - @Test(dataProvider = "Arrays") + @ParameterizedTest + @MethodSource("arrays") public void testIterator(Object[] array) { Iterator itr = Arrays.asList(array).iterator(); - for (int i = 0; i < array.length; i++) { + for (Object o : array) { assertTrue(itr.hasNext()); assertTrue(itr.hasNext()); // must be idempotent - assertSame(array[i], itr.next()); - try { - itr.remove(); - fail("Remove must throw"); - } catch (UnsupportedOperationException ex) { - // expected - } + assertSame(o, itr.next()); + assertThrows(UnsupportedOperationException.class, itr::remove); } - assertFalse(itr.hasNext()); for (int i = 0; i < 3; i++) { assertFalse(itr.hasNext()); - try { - itr.next(); - fail("Next succeed when there's no data left"); - } catch (NoSuchElementException ex) { - // expected - } + assertThrows(NoSuchElementException.class, itr::next); } } - @DataProvider(name = "Arrays") public static Object[][] arrays() { - Object[][] arrays = { + return new Object[][] { { new Object[] { } }, { new Object[] { 1 } }, { new Object[] { null } }, @@ -87,7 +76,5 @@ public class AsList { { new Object[] { "a", "a", "a", "a" } }, { IntStream.range(0, 100).boxed().toArray() } }; - - return arrays; } } diff --git a/test/jdk/java/util/Arrays/Correct.java b/test/jdk/java/util/Arrays/Correct.java index f69ea9160ff..dce169bb0fc 100644 --- a/test/jdk/java/util/Arrays/Correct.java +++ b/test/jdk/java/util/Arrays/Correct.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,19 @@ * @test * @bug 4726380 8037097 * @summary Check that different sorts give equivalent results. - * @run testng Correct * @key randomness + * @run junit Correct */ import java.util.*; -import org.testng.annotations.Test; -import org.testng.annotations.DataProvider; -import static org.testng.Assert.fail; -import static org.testng.Assert.assertEquals; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class Correct { static final Random rnd = new Random(); @@ -50,11 +52,12 @@ public class Correct { Integer[] array2 = Arrays.copyOf(array1, array1.length); Arrays.sort(array1, array1.length/3, array1.length/2); stupidSort(array2, array2.length/3, array2.length/2); - assertEquals(array1, array2, "Arrays did not match. size=" + size); + Assertions.assertArrayEquals(array2, array1, "Arrays did not match. size=" + size); } } - @Test(dataProvider = "Comparators") + @ParameterizedTest + @MethodSource("comparators") public void testComparatorSort(Comparator comparator) { for (int i=0; i comparators() { Object[][] comparators = new Object[][] { new Object[] { Comparator.naturalOrder() }, diff --git a/test/jdk/java/util/Arrays/SetAllTest.java b/test/jdk/java/util/Arrays/SetAllTest.java index 23a3578cf69..25a229d23d4 100644 --- a/test/jdk/java/util/Arrays/SetAllTest.java +++ b/test/jdk/java/util/Arrays/SetAllTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,9 @@ * @test * @bug 8012650 * @summary Unit test for setAll, parallelSetAll variants - * @run testng SetAllTest + * @run junit SetAllTest */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.util.Arrays; import java.util.function.IntFunction; @@ -37,12 +35,15 @@ import java.util.function.IntToDoubleFunction; import java.util.function.IntToLongFunction; import java.util.function.IntUnaryOperator; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.fail; +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SetAllTest { private static final IntFunction toString = i -> "N" + Integer.valueOf(i); private static final IntFunction fillString = i -> "X"; @@ -93,52 +94,51 @@ public class SetAllTest { { "fill", 3, fillDouble, new double[] { 3.14, 3.14, 3.14 }} }; - @DataProvider(name="string") public Object[][] stringTests() { return stringData; } - @DataProvider(name="int") public Object[][] intTests() { return intData; } - @DataProvider(name="long") public Object[][] longTests() { return longData; } - @DataProvider(name="double") public Object[][] doubleTests() { return doubleData; } - @Test(dataProvider = "string") + @ParameterizedTest + @MethodSource("stringTests") public void testSetAllString(String name, int size, IntFunction generator, String[] expected) { String[] result = new String[size]; Arrays.setAll(result, generator); - assertEquals(result, expected, "setAll(String[], IntFunction) case " + name + " failed."); + Assertions.assertArrayEquals(expected, result, "setAll(String[], IntFunction) case " + name + " failed."); // ensure fresh array result = new String[size]; Arrays.parallelSetAll(result, generator); - assertEquals(result, expected, "parallelSetAll(String[], IntFunction) case " + name + " failed."); + Assertions.assertArrayEquals(expected, result, "parallelSetAll(String[], IntFunction) case " + name + " failed."); } - @Test(dataProvider = "int") + @ParameterizedTest + @MethodSource("intTests") public void testSetAllInt(String name, int size, IntUnaryOperator generator, int[] expected) { int[] result = new int[size]; Arrays.setAll(result, generator); - assertEquals(result, expected, "setAll(int[], IntUnaryOperator) case " + name + " failed."); + Assertions.assertArrayEquals(expected, result, "setAll(int[], IntUnaryOperator) case " + name + " failed."); // ensure fresh array result = new int[size]; Arrays.parallelSetAll(result, generator); - assertEquals(result, expected, "parallelSetAll(int[], IntUnaryOperator) case " + name + " failed."); + Assertions.assertArrayEquals(expected, result, "parallelSetAll(int[], IntUnaryOperator) case " + name + " failed."); } - @Test(dataProvider = "long") + @ParameterizedTest + @MethodSource("longTests") public void testSetAllLong(String name, int size, IntToLongFunction generator, long[] expected) { long[] result = new long[size]; Arrays.setAll(result, generator); - assertEquals(result, expected, "setAll(long[], IntToLongFunction) case " + name + " failed."); + Assertions.assertArrayEquals(expected, result, "setAll(long[], IntToLongFunction) case " + name + " failed."); // ensure fresh array result = new long[size]; Arrays.parallelSetAll(result, generator); - assertEquals(result, expected, "parallelSetAll(long[], IntToLongFunction) case " + name + " failed."); + Assertions.assertArrayEquals(expected, result, "parallelSetAll(long[], IntToLongFunction) case " + name + " failed."); } private void assertDoubleArrayEquals(double[] actual, double[] expected, double delta, String msg) { @@ -151,7 +151,8 @@ public class SetAllTest { } } - @Test(dataProvider = "double") + @ParameterizedTest + @MethodSource("doubleTests") public void testSetAllDouble(String name, int size, IntToDoubleFunction generator, double[] expected) { double[] result = new double[size]; Arrays.setAll(result, generator); diff --git a/test/jdk/java/util/Arrays/SortingNearlySortedPrimitive.java b/test/jdk/java/util/Arrays/SortingNearlySortedPrimitive.java index b2c8d6ec45b..b9ad458688e 100644 --- a/test/jdk/java/util/Arrays/SortingNearlySortedPrimitive.java +++ b/test/jdk/java/util/Arrays/SortingNearlySortedPrimitive.java @@ -1,6 +1,6 @@ /* * Copyright 2015 Goldman Sachs. - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,11 +30,9 @@ * sorted and if so employs and optimizes merge sort rather than a * Dual-Pivot QuickSort. * - * @run testng SortingNearlySortedPrimitive + * @run junit SortingNearlySortedPrimitive */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Arrays; @@ -44,6 +42,12 @@ import java.util.function.IntFunction; import java.util.stream.IntStream; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SortingNearlySortedPrimitive { static final int BASE = 3; @@ -112,7 +116,6 @@ public class SortingNearlySortedPrimitive { } - @DataProvider(name = "shapes") public Object[][] createShapes() { Stream> baseCases = Stream.of( List.of("hiZeroLowTest", (IntFunction) this::hiZeroLowData), @@ -141,7 +144,8 @@ public class SortingNearlySortedPrimitive { return nl.toArray(); } - @Test(dataProvider = "shapes") + @ParameterizedTest + @MethodSource("createShapes") public void testShapes(String testName, IntFunction dataMethod, int size) { int[] intSourceArray = dataMethod.apply(size); diff --git a/test/jdk/java/util/Arrays/StreamAndSpliterator.java b/test/jdk/java/util/Arrays/StreamAndSpliterator.java index c28b7c4d588..eaf0b02f369 100644 --- a/test/jdk/java/util/Arrays/StreamAndSpliterator.java +++ b/test/jdk/java/util/Arrays/StreamAndSpliterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,21 +21,20 @@ * questions. */ -/** +/* * @test * @bug 8037857 * @summary tests for stream and spliterator factory methods - * @run testng StreamAndSpliterator + * @run junit StreamAndSpliterator */ -import org.testng.annotations.Test; import java.util.Arrays; import java.util.Spliterators; -import org.testng.Assert.ThrowingRunnable; - -import static org.testng.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; public class StreamAndSpliterator { @Test @@ -127,11 +126,11 @@ public class StreamAndSpliterator { assertThrowsAIOOB(() -> Spliterators.spliterator(new String[]{}, 0, 1, 0)); } - void assertThrowsNPE(ThrowingRunnable r) { + void assertThrowsNPE(Executable r) { assertThrows(NullPointerException.class, r); } - void assertThrowsAIOOB(ThrowingRunnable r) { + void assertThrowsAIOOB(Executable r) { assertThrows(ArrayIndexOutOfBoundsException.class, r); } } diff --git a/test/jdk/java/util/Arrays/TEST.properties b/test/jdk/java/util/Arrays/TEST.properties new file mode 100644 index 00000000000..8e0b6e58824 --- /dev/null +++ b/test/jdk/java/util/Arrays/TEST.properties @@ -0,0 +1 @@ +disallowedActions=testng diff --git a/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java b/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java index 41bff170259..8ebf5453187 100644 --- a/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java +++ b/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,13 +21,12 @@ * questions. */ -/** +/* * @test * @bug 8014076 8025067 * @summary unit test for Arrays.ParallelPrefix(). - * @author Tristan Yan * @modules java.management jdk.management - * @run testng/othervm -Xms256m -Xmx1024m ParallelPrefix + * @run junit/othervm -Xms256m -Xmx1024m ParallelPrefix */ import java.lang.management.ManagementFactory; @@ -40,11 +39,16 @@ import java.util.function.LongBinaryOperator; import java.util.stream.IntStream; import java.util.stream.LongStream; import com.sun.management.OperatingSystemMXBean; -import static org.testng.Assert.*; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import org.testng.annotations.BeforeSuite; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.function.Executable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ParallelPrefix { //Array size less than MIN_PARTITION private static final int SMALL_ARRAY_SIZE = 1 << 3; @@ -60,7 +64,7 @@ public class ParallelPrefix { private static int[] arraySizeCollection; - @BeforeSuite + @BeforeAll public static void setup() { java.lang.management.OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean(); @@ -90,7 +94,6 @@ public class ParallelPrefix { System.out.println("System memory is not large enough, remove large array size test"); } - @DataProvider(name = "intSet") public static Object[][] intSet(){ return genericData(size -> IntStream.range(0, size).toArray(), new IntBinaryOperator[]{ @@ -98,7 +101,6 @@ public class ParallelPrefix { Integer::min}); } - @DataProvider(name = "longSet") public static Object[][] longSet(){ return genericData(size -> LongStream.range(0, size).toArray(), new LongBinaryOperator[]{ @@ -106,7 +108,6 @@ public class ParallelPrefix { Long::min}); } - @DataProvider(name = "doubleSet") public static Object[][] doubleSet(){ return genericData(size -> IntStream.range(0, size).mapToDouble(i -> (double)i).toArray(), new DoubleBinaryOperator[]{ @@ -114,7 +115,6 @@ public class ParallelPrefix { Double::min}); } - @DataProvider(name = "stringSet") public static Object[][] stringSet(){ Function stringsFunc = size -> IntStream.range(0, size).mapToObj(Integer::toString).toArray(String[]::new); @@ -142,7 +142,8 @@ public class ParallelPrefix { return data; } - @Test(dataProvider="intSet") + @ParameterizedTest + @MethodSource("intSet") public void testParallelPrefixForInt(int[] data, int fromIndex, int toIndex, IntBinaryOperator op) { int[] sequentialResult = data.clone(); for (int index = fromIndex + 1; index < toIndex; index++) { @@ -151,14 +152,15 @@ public class ParallelPrefix { int[] parallelResult = data.clone(); Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op); - assertArraysEqual(parallelResult, sequentialResult); + assertArraysEqual(sequentialResult, parallelResult); int[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex); Arrays.parallelPrefix(parallelRangeResult, op); - assertArraysEqual(parallelRangeResult, Arrays.copyOfRange(sequentialResult, fromIndex, toIndex)); + assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult); } - @Test(dataProvider="longSet") + @ParameterizedTest + @MethodSource("longSet") public void testParallelPrefixForLong(long[] data, int fromIndex, int toIndex, LongBinaryOperator op) { long[] sequentialResult = data.clone(); for (int index = fromIndex + 1; index < toIndex; index++) { @@ -167,14 +169,15 @@ public class ParallelPrefix { long[] parallelResult = data.clone(); Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op); - assertArraysEqual(parallelResult, sequentialResult); + assertArraysEqual(sequentialResult, parallelResult); long[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex); Arrays.parallelPrefix(parallelRangeResult, op); - assertArraysEqual(parallelRangeResult, Arrays.copyOfRange(sequentialResult, fromIndex, toIndex)); + assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult); } - @Test(dataProvider="doubleSet") + @ParameterizedTest + @MethodSource("doubleSet") public void testParallelPrefixForDouble(double[] data, int fromIndex, int toIndex, DoubleBinaryOperator op) { double[] sequentialResult = data.clone(); for (int index = fromIndex + 1; index < toIndex; index++) { @@ -183,14 +186,15 @@ public class ParallelPrefix { double[] parallelResult = data.clone(); Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op); - assertArraysEqual(parallelResult, sequentialResult); + assertArraysEqual(sequentialResult, parallelResult); double[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex); Arrays.parallelPrefix(parallelRangeResult, op); - assertArraysEqual(parallelRangeResult, Arrays.copyOfRange(sequentialResult, fromIndex, toIndex)); + assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult); } - @Test(dataProvider="stringSet") + @ParameterizedTest + @MethodSource("stringSet") public void testParallelPrefixForStringr(String[] data , int fromIndex, int toIndex, BinaryOperator op) { String[] sequentialResult = data.clone(); for (int index = fromIndex + 1; index < toIndex; index++) { @@ -199,11 +203,11 @@ public class ParallelPrefix { String[] parallelResult = data.clone(); Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op); - assertArraysEqual(parallelResult, sequentialResult); + assertArraysEqual(sequentialResult, parallelResult); String[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex); Arrays.parallelPrefix(parallelRangeResult, op); - assertArraysEqual(parallelRangeResult, Arrays.copyOfRange(sequentialResult, fromIndex, toIndex)); + assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult); } @Test @@ -258,48 +262,48 @@ public class ParallelPrefix { // "library" code - private void assertThrowsNPE(ThrowingRunnable r) { + private void assertThrowsNPE(Executable r) { assertThrows(NullPointerException.class, r); } - private void assertThrowsIAE(ThrowingRunnable r) { + private void assertThrowsIAE(Executable r) { assertThrows(IllegalArgumentException.class, r); } - private void assertThrowsAIOOB(ThrowingRunnable r) { + private void assertThrowsAIOOB(Executable r) { assertThrows(ArrayIndexOutOfBoundsException.class, r); } - static void assertArraysEqual(int[] actual, int[] expected) { + static void assertArraysEqual(int[] expected, int[] actual) { try { - assertEquals(actual, expected, ""); + assertArrayEquals(expected, actual, ""); } catch (AssertionError x) { throw new AssertionError(String.format("Expected:%s, actual:%s", Arrays.toString(expected), Arrays.toString(actual)), x); } } - static void assertArraysEqual(long[] actual, long[] expected) { + static void assertArraysEqual(long[] expected, long[] actual) { try { - assertEquals(actual, expected, ""); + assertArrayEquals(expected, actual, ""); } catch (AssertionError x) { throw new AssertionError(String.format("Expected:%s, actual:%s", Arrays.toString(expected), Arrays.toString(actual)), x); } } - static void assertArraysEqual(double[] actual, double[] expected) { + static void assertArraysEqual(double[] expected, double[] actual) { try { - assertEquals(actual, expected, ""); + assertArrayEquals(expected, actual, ""); } catch (AssertionError x) { throw new AssertionError(String.format("Expected:%s, actual:%s", Arrays.toString(expected), Arrays.toString(actual)), x); } } - static void assertArraysEqual(String[] actual, String[] expected) { + static void assertArraysEqual(String[] expected, String[] actual) { try { - assertEquals(actual, expected, ""); + assertArrayEquals(expected, actual, ""); } catch (AssertionError x) { throw new AssertionError(String.format("Expected:%s, actual:%s", Arrays.toString(expected), Arrays.toString(actual)), x); From 23adf6adf09551e3d28b3db408ad2c78a79531f3 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Mon, 9 Mar 2026 10:25:49 +0000 Subject: [PATCH 112/170] 8378569: Refactor test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java to use JUnit Reviewed-by: jpai, djelinski --- test/jdk/java/net/httpclient/TEST.properties | 4 + .../httpclient/http3/H3ErrorHandlingTest.java | 189 +++++++++--------- .../http3/H3MalformedResponseTest.java | 4 +- .../http3/H3MemoryHandlingTest.java | 4 +- .../test/lib/quic/QuicServerHandler.java | 4 +- .../test/lib/quic/QuicStandaloneServer.java | 4 +- .../net/httpclient/quic/KeyUpdateTest.java | 2 +- .../net/httpclient/quic/PacketLossTest.java | 4 +- .../quic/QuicRequestResponseTest.java | 2 +- .../quic/StatelessResetReceiptTest.java | 8 +- .../quic/VersionNegotiationTest.java | 2 +- 11 files changed, 121 insertions(+), 106 deletions(-) diff --git a/test/jdk/java/net/httpclient/TEST.properties b/test/jdk/java/net/httpclient/TEST.properties index b79f7113952..77705d2f4f1 100644 --- a/test/jdk/java/net/httpclient/TEST.properties +++ b/test/jdk/java/net/httpclient/TEST.properties @@ -20,3 +20,7 @@ modules=java.base/jdk.internal.util \ java.security.jgss \ java.logging \ jdk.httpserver + +# Prevent TestNG-based tests +disallowedActions=testng + diff --git a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java index 44071ea566d..8dfef7417e3 100644 --- a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java +++ b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,6 @@ import jdk.internal.net.quic.QuicVersion; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; import jdk.test.lib.Utils; -import org.testng.IRetryAnalyzer; -import org.testng.ITestResult; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Ignore; -import org.testng.annotations.Test; import javax.net.ssl.SSLContext; import java.io.IOException; @@ -67,7 +60,14 @@ import java.util.concurrent.TimeUnit; import static java.net.http.HttpClient.Version.HTTP_3; import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; /* * @test @@ -82,17 +82,16 @@ import static org.testng.Assert.*; * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters * @build java.net.http/jdk.internal.net.http.Http3ConnectionAccess - * @run testng/othervm + * @run junit/othervm * -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors H3ErrorHandlingTest */ public class H3ErrorHandlingTest implements HttpServerAdapters { private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - private QuicStandaloneServer server; - private String requestURIBase; + private static QuicStandaloneServer server; + private static String requestURIBase; - @DataProvider public static Object[][] controlStreams() { // control / encoder / decoder return new Object[][] {{(byte)0}, {(byte)2}, {(byte)3}}; @@ -148,26 +147,22 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { return result; } - @DataProvider public static Object[][] malformedSettingsFrames() { // 2-byte ID, 2-byte value byte[] settingsFrame = new byte[]{(byte)4,(byte)4,(byte)0x40, (byte)6, (byte)0x40, (byte)6}; return chopFrame(settingsFrame, 1, 2, 3); } - @DataProvider public static Object[][] malformedCancelPushFrames() { byte[] cancelPush = new byte[]{(byte)3,(byte)2, (byte)0x40, (byte)0}; return chopFrame(cancelPush, 0, 1, 3, 9); } - @DataProvider public static Object[][] malformedGoawayFrames() { byte[] goaway = new byte[]{(byte)7,(byte)2, (byte)0x40, (byte)0}; return chopFrame(goaway, 0, 1, 3, 9); } - @DataProvider public static Object[][] malformedResponseHeadersFrames() { byte[] responseHeaders = HexFormat.of().parseHex( "011a0000"+ // headers, length 26, section prefix @@ -176,7 +171,6 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { return chopFrame(responseHeaders, 0, 1, 4, 5, 6, 7); } - @DataProvider public static Object[][] truncatedResponseFrames() { byte[] response = HexFormat.of().parseHex( "01030000"+ // headers, length 3, section prefix @@ -187,7 +181,6 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { return chopBytes(response, 1, 2, 3, 4, 6, 7, 9, 10); } - @DataProvider public static Object[][] truncatedControlFrames() { byte[] response = HexFormat.of().parseHex( "00"+ // stream type: control @@ -198,12 +191,10 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { return chopBytes(response, 2, 3, 4, 6, 7, 9, 10); } - @DataProvider public static Object[][] malformedPushPromiseFrames() { return chopFrame(valid_push_promise, 0, 1, 2, 4, 5, 6); } - @DataProvider public static Object[][] invalidControlFrames() { // frames not valid on the server control stream (after settings) // all except cancel_push / goaway (max_push_id is client-only) @@ -211,7 +202,6 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { {reserved1}, {reserved2}, {reserved3}, {reserved4}}; } - @DataProvider public static Object[][] invalidResponseFrames() { // frames not valid on the response stream // all except headers / push_promise @@ -220,7 +210,6 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { {reserved1}, {reserved2}, {reserved3}, {reserved4}}; } - @DataProvider public static Object[][] invalidPushFrames() { // frames not valid on the push promise stream // all except headers @@ -229,8 +218,8 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { {reserved1}, {reserved2}, {reserved3}, {reserved4}}; } - @BeforeClass - public void beforeClass() throws Exception { + @BeforeAll + public static void beforeClass() throws Exception { server = QuicStandaloneServer.newBuilder() .availableVersions(new QuicVersion[]{QuicVersion.QUIC_V1}) .sslContext(sslContext) @@ -242,8 +231,8 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { .port(server.getAddress().getPort()).build().toString(); } - @AfterClass - public void afterClass() throws Exception { + @AfterAll + public static void afterClass() throws Exception { if (server != null) { System.out.println("Stopping server " + server.getAddress()); server.close(); @@ -256,7 +245,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testNonSettingsFrame() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -274,10 +263,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server opens 2 control streams */ - @Test(dataProvider = "controlStreams") + @ParameterizedTest + @MethodSource("controlStreams") public void testTwoControlStreams(byte type) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream, controlStream2; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); @@ -299,10 +289,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server closes control stream */ - @Test(dataProvider = "controlStreams") + @ParameterizedTest + @MethodSource("controlStreams") public void testCloseControlStream(byte type) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var controlscheduler = SequentialScheduler.lockingScheduler(() -> {}); @@ -315,26 +306,34 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { triggerError(errorCF, Http3Error.H3_CLOSED_CRITICAL_STREAM); } - public static class RetryOnce implements IRetryAnalyzer { - boolean retried; - - @Override - public boolean retry(ITestResult iTestResult) { - if (!retried) { - retried = true; - return true; - } - return false; - } - } - /** * Server resets control stream */ - @Test(dataProvider = "controlStreams", retryAnalyzer = RetryOnce.class) + @ParameterizedTest + @MethodSource("controlStreams") public void testResetControlStream(byte type) throws Exception { + try { + System.out.printf("testResetControlStream(%s) - first attempt%n", type); + System.err.printf("%ntestResetControlStream(%s) - first attempt%n", type); + testResetControlStreamImpl(type); + System.out.printf("testResetControlStream(%s) - first attempt succeeded!%n", type); + System.err.printf("%ntestResetControlStream(%s) - first attempt succeeded!%n", type); + } catch (Throwable t) { + System.out.printf("testResetControlStream(%s) - first attempt failed: %s%n", + type, t); + System.err.printf("%ntestResetControlStream(%s) - first attempt failed: %s%n", + type); + System.out.printf("testResetControlStream(%s) - retrying...%n", type); + System.err.printf("%ntestResetControlStream(%s) - retrying...%n", type); + testResetControlStreamImpl(type); + System.out.printf("testResetControlStream(%s) - retry succeeded!%n", type); + System.err.printf("%ntestResetControlStream(%s) - retry succeeded!%n", type); + } + } + + private void testResetControlStreamImpl(byte type) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var controlscheduler = SequentialScheduler.lockingScheduler(() -> {}); @@ -362,10 +361,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends unexpected frame on control stream */ - @Test(dataProvider = "invalidControlFrames") + @ParameterizedTest + @MethodSource("invalidControlFrames") public void testUnexpectedControlFrame(byte[] frame) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -387,10 +387,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends malformed settings frame */ - @Test(dataProvider = "malformedSettingsFrames") + @ParameterizedTest + @MethodSource("malformedSettingsFrames") public void testMalformedSettingsFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -412,10 +413,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends malformed goaway frame */ - @Test(dataProvider = "malformedGoawayFrames") + @ParameterizedTest + @MethodSource("malformedGoawayFrames") public void testMalformedGoawayFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -437,10 +439,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends malformed cancel push frame */ - @Test(dataProvider = "malformedCancelPushFrames") + @ParameterizedTest + @MethodSource("malformedCancelPushFrames") public void testMalformedCancelPushFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -465,7 +468,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testInvalidGoAwaySequence() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -487,7 +490,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testInvalidGoAwayId() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -509,7 +512,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testInvalidCancelPushId() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -529,10 +532,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends unexpected frame on push stream */ - @Test(dataProvider = "invalidPushFrames") + @ParameterizedTest + @MethodSource("invalidPushFrames") public void testUnexpectedPushFrame(byte[] frame) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream pushStream; pushStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -556,10 +560,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends malformed frame on push stream */ - @Test(dataProvider = "malformedResponseHeadersFrames") + @ParameterizedTest + @MethodSource("malformedResponseHeadersFrames") public void testMalformedPushStreamFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream pushStream; pushStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -585,10 +590,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends malformed frame on push stream */ - @Test(dataProvider = "malformedPushPromiseFrames") + @ParameterizedTest + @MethodSource("malformedPushPromiseFrames") public void testMalformedPushPromiseFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { // write PUSH_PROMISE frame s.outputStream().write(frame); // ignore the request stream; we're expecting the client to close the connection @@ -605,7 +611,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testDuplicatePushStream() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream pushStream, pushStream2; pushStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); pushStream2 = c.openNewLocalUniStream(Duration.ZERO).resultNow(); @@ -634,7 +640,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testInvalidPushPromiseId() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { // write PUSH_PROMISE frame s.outputStream().write(huge_id_push_promise); // ignore the request stream; we're expecting the client to close the connection @@ -649,7 +655,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testInvalidPushStreamId() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream pushStream; pushStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -669,10 +675,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends unexpected frame on response stream */ - @Test(dataProvider = "invalidResponseFrames") + @ParameterizedTest + @MethodSource("invalidResponseFrames") public void testUnexpectedResponseFrame(byte[] frame) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { s.outputStream().write(frame); // ignore the request stream; we're expecting the client to close the connection completeUponTermination(c, errorCF); @@ -683,10 +690,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server sends malformed headers frame on response stream */ - @Test(dataProvider = "malformedResponseHeadersFrames") + @ParameterizedTest + @MethodSource("malformedResponseHeadersFrames") public void testMalformedResponseFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { s.outputStream().write(frame); // ignore the request stream; we're expecting the client to close the connection completeUponTermination(c, errorCF); @@ -699,10 +707,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server truncates a frame on the response stream */ - @Test(dataProvider = "truncatedResponseFrames") + @ParameterizedTest + @MethodSource("truncatedResponseFrames") public void testTruncatedResponseFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { try (OutputStream outputStream = s.outputStream()) { outputStream.write(frame); } @@ -715,10 +724,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server truncates a frame on the control stream */ - @Test(dataProvider = "truncatedControlFrames") + @ParameterizedTest + @MethodSource("truncatedControlFrames") public void testTruncatedControlFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var controlscheduler = SequentialScheduler.lockingScheduler(() -> {}); @@ -735,10 +745,11 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { /** * Server truncates a frame on the push stream */ - @Test(dataProvider = "truncatedResponseFrames") + @ParameterizedTest + @MethodSource("truncatedResponseFrames") public void testTruncatedPushStreamFrame(byte[] frame, int bytes) throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream pushStream; pushStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -765,7 +776,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { @Test public void testReservedSettingsFrames() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream controlStream; controlStream = c.openNewLocalUniStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -785,7 +796,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { */ @Test public void testStatelessReset() throws Exception { - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { // stateless reset QuicConnectionId localConnId = c.localConnectionId(); ByteBuffer resetDatagram = c.endpoint().idFactory().statelessReset(localConnId.asReadOnlyBuffer(), 43); @@ -819,10 +830,10 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { * Server opens a bidi stream */ @Test - @Ignore("BiDi streams are rejected by H3 client at QUIC level") + @Disabled("BiDi streams are rejected by H3 client at QUIC level") public void testBidiStream() throws Exception { CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { QuicSenderStream bidiStream; bidiStream = c.openNewLocalBidiStream(Duration.ZERO).resultNow(); var scheduler = SequentialScheduler.lockingScheduler(() -> { @@ -842,7 +853,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { */ @Test public void testConnectionCloseQUIC() throws Exception { - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { TerminationCause tc = TerminationCause.forException( new QuicTransportException("ignored", null, 0, QuicTransportErrors.INTERNAL_ERROR) @@ -859,7 +870,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { */ @Test public void testConnectionCloseCryptoQUIC() throws Exception { - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { TerminationCause tc = TerminationCause.forException( new QuicTransportException("ignored", null, 0, QuicTransportErrors.CRYPTO_ERROR.from() + 80 /*Alert.INTERNAL_ERROR.id*/, null) @@ -876,7 +887,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { */ @Test public void testConnectionCloseUnknownCryptoQUIC() throws Exception { - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { TerminationCause tc = TerminationCause.forException( new QuicTransportException("ignored", null, 0, QuicTransportErrors.CRYPTO_ERROR.from() + 5, null) @@ -893,7 +904,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { */ @Test public void testConnectionCloseUnknownQUIC() throws Exception { - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { TerminationCause tc = TerminationCause.forException( new QuicTransportException("ignored", null, 0, QuicTransportErrors.CRYPTO_ERROR.to() + 1 /*0x200*/, null) @@ -910,7 +921,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { */ @Test public void testConnectionCloseH3() throws Exception { - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { TerminationCause tc = TerminationCause.appLayerClose(Http3Error.H3_EXCESSIVE_LOAD.code()); tc.peerVisibleReason("testtest"); c.connectionTerminator().terminate(tc); @@ -924,7 +935,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { */ @Test public void testConnectionCloseH3Unknown() throws Exception { - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { TerminationCause tc = TerminationCause.appLayerClose(0x1f21); tc.peerVisibleReason("testtest"); c.connectionTerminator().terminate(tc); @@ -974,7 +985,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { System.out.println("Server reason: \"" + terminationCause.getPeerVisibleReason()+'"'); final long actual = terminationCause.getCloseCode(); // expected - assertEquals(actual, expected.code(), "Expected " + toHexString(expected) + " got 0x" + Long.toHexString(actual)); + assertEquals(expected.code(), actual, "Expected " + toHexString(expected) + " got 0x" + Long.toHexString(actual)); } finally { client.shutdownNow(); } @@ -1027,7 +1038,7 @@ public class H3ErrorHandlingTest implements HttpServerAdapters { System.out.println("Server reason: \"" + terminationCause.getPeerVisibleReason()+'"'); final long actual = terminationCause.getCloseCode(); // expected - assertEquals(actual, http3Error.code(), "Expected " + toHexString(http3Error) + " got 0x" + Long.toHexString(actual)); + assertEquals(http3Error.code(), actual, "Expected " + toHexString(http3Error) + " got 0x" + Long.toHexString(actual)); } finally { client.shutdownNow(); } diff --git a/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java b/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java index 5ef45f8b230..eaab2711479 100644 --- a/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java +++ b/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -458,7 +458,7 @@ class H3MalformedResponseTest { private static BooleanSupplier configureServerResponse(byte[] serverResponseBytes) { var connectionTerminated = new AtomicBoolean(); - SERVER.addHandler((c, s)-> { + SERVER.setHandler((c, s)-> { try (OutputStream outputStream = s.outputStream()) { outputStream.write(serverResponseBytes); } diff --git a/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java b/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java index 2fcb7388f7b..0d107486fcd 100644 --- a/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java +++ b/test/jdk/java/net/httpclient/http3/H3MemoryHandlingTest.java @@ -109,7 +109,7 @@ public class H3MemoryHandlingTest implements HttpServerAdapters { "00ffffffffffffffff"); // data, 2^62 - 1 bytes byte[] kilo = new byte[1024]; final CompletableFuture serverAllWritesDone = new CompletableFuture<>(); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { // verify that the connection stays open completeUponTermination(c, errorCF); try (OutputStream outputStream = s.outputStream()) { @@ -154,7 +154,7 @@ public class H3MemoryHandlingTest implements HttpServerAdapters { byte[] kilo = new byte[1024]; CountDownLatch writerBlocked = new CountDownLatch(1); - server.addHandler((c,s)-> { + server.setHandler((c, s)-> { // verify that the connection stays open completeUponTermination(c, errorCF); QuicBidiStream qs = s.underlyingBidiStream(); diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicServerHandler.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicServerHandler.java index 886f15821a6..bef2e40137b 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicServerHandler.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicServerHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ import jdk.internal.net.http.quic.streams.QuicBidiStream; * Used by server side application code to handle incoming Quic connections and streams associated * with those connections * - * @see QuicStandaloneServer#addHandler(QuicServerHandler) + * @see QuicStandaloneServer#setHandler(QuicServerHandler) */ // TODO: should we make this an abstract class instead of interface? public interface QuicServerHandler { diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicStandaloneServer.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicStandaloneServer.java index b1697064556..a7b5bb42ac2 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicStandaloneServer.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/quic/QuicStandaloneServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ public final class QuicStandaloneServer extends QuicServer { setConnectionAcceptor(QuicStandaloneServer::acceptIncoming); } - public void addHandler(final QuicServerHandler handler) { + public void setHandler(final QuicServerHandler handler) { this.handler = handler; } diff --git a/test/jdk/java/net/httpclient/quic/KeyUpdateTest.java b/test/jdk/java/net/httpclient/quic/KeyUpdateTest.java index d13b8d9b865..eaec0bc8b95 100644 --- a/test/jdk/java/net/httpclient/quic/KeyUpdateTest.java +++ b/test/jdk/java/net/httpclient/quic/KeyUpdateTest.java @@ -102,7 +102,7 @@ public class KeyUpdateTest { .sslContext(sslContext) .build(); // add a handler which deals with incoming connections - server.addHandler(handler); + server.setHandler(handler); server.start(); System.out.println("Server started at " + server.getAddress()); } diff --git a/test/jdk/java/net/httpclient/quic/PacketLossTest.java b/test/jdk/java/net/httpclient/quic/PacketLossTest.java index 1f75e1feb95..a597c826e73 100644 --- a/test/jdk/java/net/httpclient/quic/PacketLossTest.java +++ b/test/jdk/java/net/httpclient/quic/PacketLossTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -158,7 +158,7 @@ public class PacketLossTest { private static void startServer(final QuicStandaloneServer server) throws IOException { // add a handler which deals with incoming connections - server.addHandler(new EchoHandler(HELLO_MSG.length)); + server.setHandler(new EchoHandler(HELLO_MSG.length)); server.start(); System.out.println("Server " + server.name() + " started at " + server.getAddress()); } diff --git a/test/jdk/java/net/httpclient/quic/QuicRequestResponseTest.java b/test/jdk/java/net/httpclient/quic/QuicRequestResponseTest.java index 208e284cefd..2393ac7df12 100644 --- a/test/jdk/java/net/httpclient/quic/QuicRequestResponseTest.java +++ b/test/jdk/java/net/httpclient/quic/QuicRequestResponseTest.java @@ -73,7 +73,7 @@ public class QuicRequestResponseTest { .sslContext(sslContext) .build(); // add a handler which deals with incoming connections - server.addHandler(new EchoHandler(HELLO_MSG.length)); + server.setHandler(new EchoHandler(HELLO_MSG.length)); server.start(); System.out.println("Server started at " + server.getAddress()); } diff --git a/test/jdk/java/net/httpclient/quic/StatelessResetReceiptTest.java b/test/jdk/java/net/httpclient/quic/StatelessResetReceiptTest.java index a20494095bd..9f7852740b4 100644 --- a/test/jdk/java/net/httpclient/quic/StatelessResetReceiptTest.java +++ b/test/jdk/java/net/httpclient/quic/StatelessResetReceiptTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,7 +128,7 @@ public class StatelessResetReceiptTest { public void testActiveConnection() throws Exception { final CompletableFuture serverConnCF = new MinimalFuture<>(); final NotifyingHandler handler = new NotifyingHandler(serverConnCF); - server.addHandler(handler); + server.setHandler(handler); try (final QuicClient client = createClient()) { // create a QUIC connection to the server final ClientConnection conn = ClientConnection.establishConnection(client, @@ -162,7 +162,7 @@ public class StatelessResetReceiptTest { public void testClosingConnection() throws Exception { final CompletableFuture serverConnCF = new MinimalFuture<>(); final NotifyingHandler handler = new NotifyingHandler(serverConnCF); - server.addHandler(handler); + server.setHandler(handler); try (final QuicClient client = createClient()) { // create a QUIC connection to the server final ClientConnection conn = ClientConnection.establishConnection(client, @@ -215,7 +215,7 @@ public class StatelessResetReceiptTest { public void testDrainingConnection() throws Exception { final CompletableFuture serverConnCF = new MinimalFuture<>(); final NotifyingHandler handler = new NotifyingHandler(serverConnCF); - server.addHandler(handler); + server.setHandler(handler); try (final QuicClient client = createClient()) { // create a QUIC connection to the server final ClientConnection conn = ClientConnection.establishConnection(client, diff --git a/test/jdk/java/net/httpclient/quic/VersionNegotiationTest.java b/test/jdk/java/net/httpclient/quic/VersionNegotiationTest.java index bd5bbae0170..6b40bf84a8e 100644 --- a/test/jdk/java/net/httpclient/quic/VersionNegotiationTest.java +++ b/test/jdk/java/net/httpclient/quic/VersionNegotiationTest.java @@ -126,7 +126,7 @@ public class VersionNegotiationTest { .availableVersions(new QuicVersion[]{version}) .sslContext(sslContext) .build(); - server.addHandler(new ExceptionThrowingHandler()); + server.setHandler(new ExceptionThrowingHandler()); server.start(); System.out.println("Quic server with version " + version + " started at " + server.getAddress()); return server; From 5e588085e9c333e9ad8e48dd7c60e665d30e278d Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 9 Mar 2026 10:35:00 +0000 Subject: [PATCH 113/170] 8378744: Obsolete NewSizeThreadIncrease flag Reviewed-by: tschatzl, iwalulya, sjohanss --- .../cpu/aarch64/c1_globals_aarch64.hpp | 1 - .../cpu/aarch64/c2_globals_aarch64.hpp | 1 - src/hotspot/cpu/arm/c1_globals_arm.hpp | 1 - src/hotspot/cpu/arm/c2_globals_arm.hpp | 1 - src/hotspot/cpu/ppc/c1_globals_ppc.hpp | 1 - src/hotspot/cpu/ppc/c2_globals_ppc.hpp | 1 - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 1 - src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 1 - src/hotspot/cpu/s390/c1_globals_s390.hpp | 1 - src/hotspot/cpu/s390/c2_globals_s390.hpp | 1 - src/hotspot/cpu/x86/c1_globals_x86.hpp | 1 - src/hotspot/cpu/x86/c2_globals_x86.hpp | 1 - .../share/compiler/compilerDefinitions.cpp | 3 - .../share/compiler/compiler_globals_pd.hpp | 1 - .../share/gc/serial/defNewGeneration.cpp | 40 +----- .../share/gc/serial/defNewGeneration.hpp | 9 -- src/hotspot/share/gc/shared/gc_globals.hpp | 5 - src/hotspot/share/runtime/arguments.cpp | 1 + .../arguments/TestNewSizeThreadIncrease.java | 127 ------------------ .../optionsvalidation/JVMOptionsUtils.java | 3 - 20 files changed, 2 insertions(+), 199 deletions(-) delete mode 100644 test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java diff --git a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp index 938a64dd399..df013d9d1ee 100644 --- a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp @@ -42,7 +42,6 @@ define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 1500 ); define_pd_global(intx, OnStackReplacePercentage, 933 ); -define_pd_global(intx, NewSizeThreadIncrease, 4*K ); define_pd_global(size_t, InitialCodeCacheSize, 160*K); define_pd_global(size_t, ReservedCodeCacheSize, 32*M ); define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); diff --git a/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp index a0dea3643a1..87ad9caaa45 100644 --- a/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp @@ -47,7 +47,6 @@ define_pd_global(intx, ConditionalMoveLimit, 3); define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, MinJumpTableSize, 10); define_pd_global(intx, InteriorEntryAlignment, 16); -define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); // InitialCodeCacheSize derived from specjbb2000 run. diff --git a/src/hotspot/cpu/arm/c1_globals_arm.hpp b/src/hotspot/cpu/arm/c1_globals_arm.hpp index 1fe5f1a23ee..992cfd0e408 100644 --- a/src/hotspot/cpu/arm/c1_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c1_globals_arm.hpp @@ -43,7 +43,6 @@ define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 1500 ); define_pd_global(intx, OnStackReplacePercentage, 933 ); -define_pd_global(size_t, NewSizeThreadIncrease, 4*K ); define_pd_global(size_t, InitialCodeCacheSize, 160*K); define_pd_global(size_t, ReservedCodeCacheSize, 32*M ); define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); diff --git a/src/hotspot/cpu/arm/c2_globals_arm.hpp b/src/hotspot/cpu/arm/c2_globals_arm.hpp index 0849bd594f0..84abde5650b 100644 --- a/src/hotspot/cpu/arm/c2_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c2_globals_arm.hpp @@ -47,7 +47,6 @@ define_pd_global(intx, ConditionalMoveLimit, 4); // C2 gets to use all the float/double registers define_pd_global(intx, FreqInlineSize, 175); define_pd_global(intx, InteriorEntryAlignment, 16); // = CodeEntryAlignment -define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K)); // The default setting 16/16 seems to work best. // (For _228_jack 16/16 is 2% better than 4/4, 16/4, 32/32, 32/16, or 16/32.) //define_pd_global(intx, OptoLoopAlignment, 16); // = 4*wordSize diff --git a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp index 77d9acd1cd1..7d2e44a88b6 100644 --- a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp @@ -52,7 +52,6 @@ define_pd_global(size_t, CodeCacheExpansionSize, 32*K); define_pd_global(size_t, CodeCacheMinBlockLength, 1); define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true); -define_pd_global(size_t, NewSizeThreadIncrease, 16*K); define_pd_global(size_t, InitialCodeCacheSize, 160*K); #endif // !COMPILER2 diff --git a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp index caef322d4a1..eeff8d93dd4 100644 --- a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp @@ -47,7 +47,6 @@ define_pd_global(intx, ConditionalMoveLimit, 3); define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, MinJumpTableSize, 10); define_pd_global(intx, InteriorEntryAlignment, 16); -define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, RegisterCostAreaRatio, 16000); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp index b15bb5c23c3..00b92a0dec3 100644 --- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp @@ -42,7 +42,6 @@ define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 1500 ); define_pd_global(intx, OnStackReplacePercentage, 933 ); -define_pd_global(intx, NewSizeThreadIncrease, 4*K ); define_pd_global(size_t, InitialCodeCacheSize, 160*K); define_pd_global(size_t, ReservedCodeCacheSize, 32*M ); define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp index 648c24ee98b..afb4ae8fcdd 100644 --- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp @@ -47,7 +47,6 @@ define_pd_global(intx, ConditionalMoveLimit, 3); define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, MinJumpTableSize, 10); define_pd_global(intx, InteriorEntryAlignment, 16); -define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); // InitialCodeCacheSize derived from specjbb2000 run. diff --git a/src/hotspot/cpu/s390/c1_globals_s390.hpp b/src/hotspot/cpu/s390/c1_globals_s390.hpp index 25e46cd1509..bd07dd87066 100644 --- a/src/hotspot/cpu/s390/c1_globals_s390.hpp +++ b/src/hotspot/cpu/s390/c1_globals_s390.hpp @@ -52,7 +52,6 @@ define_pd_global(size_t, CodeCacheExpansionSize, 32*K); define_pd_global(size_t, CodeCacheMinBlockLength, 1); define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true); -define_pd_global(size_t, NewSizeThreadIncrease, 16*K); define_pd_global(size_t, InitialCodeCacheSize, 160*K); #endif // !COMPILER2 diff --git a/src/hotspot/cpu/s390/c2_globals_s390.hpp b/src/hotspot/cpu/s390/c2_globals_s390.hpp index 125b317588d..068511be8f3 100644 --- a/src/hotspot/cpu/s390/c2_globals_s390.hpp +++ b/src/hotspot/cpu/s390/c2_globals_s390.hpp @@ -46,7 +46,6 @@ define_pd_global(intx, OnStackReplacePercentage, 140); define_pd_global(intx, ConditionalMoveLimit, 4); define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, InteriorEntryAlignment, 4); -define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, RegisterCostAreaRatio, 12000); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); diff --git a/src/hotspot/cpu/x86/c1_globals_x86.hpp b/src/hotspot/cpu/x86/c1_globals_x86.hpp index 978b233bb63..063a9185d53 100644 --- a/src/hotspot/cpu/x86/c1_globals_x86.hpp +++ b/src/hotspot/cpu/x86/c1_globals_x86.hpp @@ -41,7 +41,6 @@ define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 1500 ); define_pd_global(intx, OnStackReplacePercentage, 933 ); -define_pd_global(size_t, NewSizeThreadIncrease, 4*K ); define_pd_global(size_t, InitialCodeCacheSize, 160*K); define_pd_global(size_t, ReservedCodeCacheSize, 32*M ); define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); diff --git a/src/hotspot/cpu/x86/c2_globals_x86.hpp b/src/hotspot/cpu/x86/c2_globals_x86.hpp index 3f616cb4578..bc119693d32 100644 --- a/src/hotspot/cpu/x86/c2_globals_x86.hpp +++ b/src/hotspot/cpu/x86/c2_globals_x86.hpp @@ -46,7 +46,6 @@ define_pd_global(intx, FreqInlineSize, 325); define_pd_global(intx, MinJumpTableSize, 10); define_pd_global(intx, LoopPercentProfileLimit, 10); define_pd_global(intx, InteriorEntryAlignment, 16); -define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); // InitialCodeCacheSize derived from specjbb2000 run. define_pd_global(size_t, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index 9bd6e893bcd..b8244036835 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -447,9 +447,6 @@ void CompilerConfig::set_jvmci_specific_flags() { if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) { FLAG_SET_DEFAULT(InitialCodeCacheSize, MAX2(16*M, InitialCodeCacheSize)); } - if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) { - FLAG_SET_DEFAULT(NewSizeThreadIncrease, MAX2(4*K, NewSizeThreadIncrease)); - } if (FLAG_IS_DEFAULT(Tier3DelayOn)) { // This effectively prevents the compile broker scheduling tier 2 // (i.e., limited C1 profiling) compilations instead of tier 3 diff --git a/src/hotspot/share/compiler/compiler_globals_pd.hpp b/src/hotspot/share/compiler/compiler_globals_pd.hpp index 6a87fdaaaf1..537a7f030fb 100644 --- a/src/hotspot/share/compiler/compiler_globals_pd.hpp +++ b/src/hotspot/share/compiler/compiler_globals_pd.hpp @@ -58,7 +58,6 @@ define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 0); define_pd_global(intx, OnStackReplacePercentage, 0); -define_pd_global(size_t, NewSizeThreadIncrease, 4*K); define_pd_global(bool, InlineClassNatives, true); define_pd_global(bool, InlineUnsafeOps, true); define_pd_global(size_t, InitialCodeCacheSize, 160*K); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 225f15f785f..ec3726d1dce 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -349,38 +349,6 @@ void DefNewGeneration::expand_eden_by(size_t delta_bytes) { post_resize(); } -size_t DefNewGeneration::calculate_thread_increase_size(int threads_count) const { - size_t thread_increase_size = 0; - // Check an overflow at 'threads_count * NewSizeThreadIncrease'. - if (threads_count > 0 && NewSizeThreadIncrease <= max_uintx / threads_count) { - thread_increase_size = threads_count * NewSizeThreadIncrease; - } - return thread_increase_size; -} - -size_t DefNewGeneration::adjust_for_thread_increase(size_t new_size_candidate, - size_t new_size_before, - size_t alignment, - size_t thread_increase_size) const { - size_t desired_new_size = new_size_before; - - if (NewSizeThreadIncrease > 0 && thread_increase_size > 0) { - - // 1. Check an overflow at 'new_size_candidate + thread_increase_size'. - if (new_size_candidate <= max_uintx - thread_increase_size) { - new_size_candidate += thread_increase_size; - - // 2. Check an overflow at 'align_up'. - size_t aligned_max = ((max_uintx - alignment) & ~(alignment-1)); - if (new_size_candidate <= aligned_max) { - desired_new_size = align_up(new_size_candidate, alignment); - } - } - } - - return desired_new_size; -} - size_t DefNewGeneration::calculate_desired_young_gen_bytes() const { size_t old_size = SerialHeap::heap()->old_gen()->capacity(); size_t new_size_before = _virtual_space.committed_size(); @@ -392,14 +360,8 @@ size_t DefNewGeneration::calculate_desired_young_gen_bytes() const { // All space sizes must be multiples of Generation::GenGrain. size_t alignment = Generation::GenGrain; - int threads_count = Threads::number_of_non_daemon_threads(); - size_t thread_increase_size = calculate_thread_increase_size(threads_count); - size_t new_size_candidate = old_size / NewRatio; - // Compute desired new generation size based on NewRatio and NewSizeThreadIncrease - // and reverts to previous value if any overflow happens - size_t desired_new_size = adjust_for_thread_increase(new_size_candidate, new_size_before, - alignment, thread_increase_size); + size_t desired_new_size = align_up(new_size_candidate, alignment); // Adjust new generation size desired_new_size = clamp(desired_new_size, min_new_size, max_new_size); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 98e599ffeaf..21241ec00ef 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -229,15 +229,6 @@ class DefNewGeneration: public Generation { // Initialize eden/from/to spaces. void init_spaces(); - // Return adjusted new size for NewSizeThreadIncrease. - // If any overflow happens, revert to previous new size. - size_t adjust_for_thread_increase(size_t new_size_candidate, - size_t new_size_before, - size_t alignment, - size_t thread_increase_size) const; - - size_t calculate_thread_increase_size(int threads_count) const; - // Scavenge support void swap_spaces(); diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 65c970435e5..2fd062de648 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -480,11 +480,6 @@ "Ratio of old/new generation sizes") \ range(0, max_uintx-1) \ \ - product_pd(size_t, NewSizeThreadIncrease, \ - "Additional size added to desired new generation size per " \ - "non-daemon thread (in bytes)") \ - range(0, max_uintx) \ - \ product(uintx, QueuedAllocationWarningCount, 0, \ "Number of times an allocation that queues behind a GC " \ "will retry before printing a warning") \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index a1dae76f680..11c4853c388 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -553,6 +553,7 @@ static SpecialFlag const special_jvm_flags[] = { { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, { "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, { "MaxRAM", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, + { "NewSizeThreadIncrease", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, diff --git a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java b/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java deleted file mode 100644 index f885ef7e462..00000000000 --- a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package gc.arguments; - -/* - * @test TestNewSizeThreadIncrease - * @bug 8144527 - * @summary Tests argument processing for NewSizeThreadIncrease - * @library /test/lib - * @library / - * @requires vm.gc.Serial - * @requires test.thread.factory == null - * @modules java.base/jdk.internal.misc - * java.management - * @run driver gc.arguments.TestNewSizeThreadIncrease - */ - - -import jdk.test.lib.Platform; -import jdk.test.lib.process.OutputAnalyzer; - -// Range of NewSizeThreadIncrease is 0 ~ max_uintx. -// Total of 5 threads will be created (1 GCTest thread and 4 TestThread). -public class TestNewSizeThreadIncrease { - static final String VALID_VALUE = "2097152"; // 2MB - - // This value will make an overflow of 'thread count * NewSizeThreadIncrease' at DefNewGeneration::compute_new_size(). - // = (max_uintx / 5) + 1, = (18446744073709551615 / 5) + 1 - static String INVALID_VALUE_1 = "3689348814741910324"; - - // This string is contained when compute_new_size() expands or shrinks. - static final String LOG_NEWSIZE_CHANGED = "New generation size "; - - public static void main(String[] args) throws Exception { - if (Platform.is32bit()) { - // (max_uintx / 5) + 1, 4294967295/5 + 1 - INVALID_VALUE_1 = "858993460"; - } - - // New size will be applied as NewSizeThreadIncrease is small enough to expand. - runNewSizeThreadIncreaseTest(VALID_VALUE, true); - - // New size will be ignored as 'thread count * NewSizeThreadIncrease' overflows. - runNewSizeThreadIncreaseTest(INVALID_VALUE_1, false); - } - - static void runNewSizeThreadIncreaseTest(String expectedValue, boolean isNewsizeChanged) throws Exception { - OutputAnalyzer output = GCArguments.executeLimitedTestJava("-XX:+UseSerialGC", - "-Xms96M", - "-Xmx128M", - "-XX:NewRatio=2", - "-Xlog:gc+heap+ergo=debug", - "-XX:NewSizeThreadIncrease="+expectedValue, - GCTest.class.getName()); - - output.shouldHaveExitValue(0); - - if (isNewsizeChanged) { - output.shouldContain(LOG_NEWSIZE_CHANGED); - } else { - output.shouldNotContain(LOG_NEWSIZE_CHANGED); - } - } - - static class GCTest { - - static final int MAX_THREADS_COUNT = 4; - static TestThread threads[] = new TestThread[MAX_THREADS_COUNT]; - - public static void main(String[] args) { - - System.out.println("Creating garbage"); - - for (int i=0; i Date: Mon, 9 Mar 2026 11:43:36 +0000 Subject: [PATCH 114/170] 8379411: Use TestFramework scenarios in 837841 Reviewed-by: qamai, dfenacci, chagedorn --- .../compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java b/test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java index a1f4f011466..dd446d8bb25 100644 --- a/test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java +++ b/test/hotspot/jtreg/compiler/c2/gvn/MissedURShiftIAddILShiftIdeal.java @@ -24,6 +24,7 @@ package compiler.c2.gvn; import compiler.lib.ir_framework.*; import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; import jdk.test.lib.Utils; import java.util.Random; @@ -35,15 +36,18 @@ import java.util.Random; * regardless of Add input order, i.e. it is commutative w.r.t. the addition. * @library /test/lib / * @run driver ${test.main.class} - * @run driver ${test.main.class} -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:VerifyIterativeGVN=1110 -Xbatch -XX:CompileCommand=compileonly,${test.main.class}::* */ public class MissedURShiftIAddILShiftIdeal { private static final Random RANDOM = Utils.getRandomInstance(); public static void main(String[] args) { - TestFramework.run(); + var framework = new TestFramework(); + framework.addScenarios(new Scenario(0)); + if (Platform.isDebugBuild()) { + framework.addScenarios(new Scenario(1, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:VerifyIterativeGVN=1110")); + } + framework.start(); } @Run(test = {"testI", "testICommuted", "testIComputedY", From e69fb7765af995be121bd0d7573a204312436183 Mon Sep 17 00:00:00 2001 From: April Date: Mon, 9 Mar 2026 11:52:42 +0000 Subject: [PATCH 115/170] 8378177: AllowExtshm flag cleanup on AIX Reviewed-by: mdoerr, stuefe --- src/hotspot/os/aix/globals_aix.hpp | 10 --------- src/hotspot/os/aix/os_aix.cpp | 34 +++--------------------------- src/hotspot/os/aix/os_aix.hpp | 11 ---------- 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/src/hotspot/os/aix/globals_aix.hpp b/src/hotspot/os/aix/globals_aix.hpp index 473d7759063..adc189666ef 100644 --- a/src/hotspot/os/aix/globals_aix.hpp +++ b/src/hotspot/os/aix/globals_aix.hpp @@ -37,16 +37,6 @@ range, \ constraint) \ \ - /* Whether to allow the VM to run if EXTSHM=ON. EXTSHM is an environment */ \ - /* variable used on AIX to activate certain hacks which allow more shm segments */\ - /* for 32bit processes. For 64bit processes, it is pointless and may have */ \ - /* harmful side effects (e.g. for some reasonn prevents allocation of 64k pages */\ - /* via shmctl). */ \ - /* Per default we quit with an error if that variable is found; for certain */ \ - /* customer scenarios, we may want to be able to run despite that variable. */ \ - product(bool, AllowExtshm, false, DIAGNOSTIC, \ - "Allow VM to run with EXTSHM=ON.") \ - \ /* Maximum expected size of the data segment. That correlates with the */ \ /* maximum C Heap consumption we expect. */ \ /* We need to leave "breathing space" for the data segment when */ \ diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index af743dc7484..7c08d6de2db 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -126,7 +126,6 @@ int mread_real_time(timebasestruct_t *t, size_t size_of_timebasestruct_t); // for multipage initialization error analysis (in 'g_multipage_error') #define ERROR_MP_OS_TOO_OLD 100 -#define ERROR_MP_EXTSHM_ACTIVE 101 #define ERROR_MP_VMGETINFO_FAILED 102 #define ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K 103 @@ -178,9 +177,6 @@ uint32_t os::Aix::_os_version = 0; // -1 = uninitialized, 0 - no, 1 - yes int os::Aix::_xpg_sus_mode = -1; -// -1 = uninitialized, 0 - no, 1 - yes -int os::Aix::_extshm = -1; - //////////////////////////////////////////////////////////////////////////////// // local variables @@ -1195,13 +1191,6 @@ void os::print_memory_info(outputStream* st) { const char* const ldr_cntrl = ::getenv("LDR_CNTRL"); st->print_cr(" LDR_CNTRL=%s.", ldr_cntrl ? ldr_cntrl : ""); - // Print out EXTSHM because it is an unsupported setting. - const char* const extshm = ::getenv("EXTSHM"); - st->print_cr(" EXTSHM=%s.", extshm ? extshm : ""); - if ( (strcmp(extshm, "on") == 0) || (strcmp(extshm, "ON") == 0) ) { - st->print_cr(" *** Unsupported! Please remove EXTSHM from your environment! ***"); - } - // Print out AIXTHREAD_GUARDPAGES because it affects the size of pthread stacks. const char* const aixthread_guardpages = ::getenv("AIXTHREAD_GUARDPAGES"); st->print_cr(" AIXTHREAD_GUARDPAGES=%s.", @@ -2133,8 +2122,6 @@ void os::init(void) { // datapsize = 64k. Data segment, thread stacks are 64k paged. // This normally means that we can allocate 64k pages dynamically. - // (There is one special case where this may be false: EXTSHM=on. - // but we decided to not support that mode). assert0(g_multipage_support.can_use_64K_pages || g_multipage_support.can_use_64K_mmap_pages); set_page_size(64*K); @@ -2543,28 +2530,13 @@ void os::Aix::initialize_os_info() { void os::Aix::scan_environment() { char* p; - int rc; - // Warn explicitly if EXTSHM=ON is used. That switch changes how - // System V shared memory behaves. One effect is that page size of - // shared memory cannot be change dynamically, effectivly preventing - // large pages from working. - // This switch was needed on AIX 32bit, but on AIX 64bit the general - // recommendation is (in OSS notes) to switch it off. + // Reject EXTSHM=ON. That switch changes how System V shared memory behaves + // and prevents allocation of 64k pages for the heap. p = ::getenv("EXTSHM"); trcVerbose("EXTSHM=%s.", p ? p : ""); if (p && strcasecmp(p, "ON") == 0) { - _extshm = 1; - log_warning(os)("*** Unsupported mode! Please remove EXTSHM from your environment! ***"); - if (!AllowExtshm) { - // We allow under certain conditions the user to continue. However, we want this - // to be a fatal error by default. On certain AIX systems, leaving EXTSHM=ON means - // that the VM is not able to allocate 64k pages for the heap. - // We do not want to run with reduced performance. - vm_exit_during_initialization("EXTSHM is ON. Please remove EXTSHM from your environment."); - } - } else { - _extshm = 0; + vm_exit_during_initialization("EXTSHM is ON. Please remove EXTSHM from your environment."); } // SPEC1170 behaviour: will change the behaviour of a number of POSIX APIs. diff --git a/src/hotspot/os/aix/os_aix.hpp b/src/hotspot/os/aix/os_aix.hpp index a30e2077fc2..e21d2cf81bb 100644 --- a/src/hotspot/os/aix/os_aix.hpp +++ b/src/hotspot/os/aix/os_aix.hpp @@ -49,11 +49,6 @@ class os::Aix { // 1 - SPEC1170 requested (XPG_SUS_ENV is ON) static int _xpg_sus_mode; - // -1 = uninitialized, - // 0 - EXTSHM=OFF or not set - // 1 - EXTSHM=ON - static int _extshm; - static bool available_memory(physical_memory_size_type& value); static bool free_memory(physical_memory_size_type& value); static physical_memory_size_type physical_memory() { return _physical_memory; } @@ -111,12 +106,6 @@ class os::Aix { return _xpg_sus_mode; } - // Returns true if EXTSHM=ON. - static bool extshm() { - assert(_extshm != -1, "not initialized"); - return _extshm; - } - // result struct for get_meminfo() struct meminfo_t { From de47ffa92f6c4320eb1cc0e38894512487b98c71 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 9 Mar 2026 11:54:33 +0000 Subject: [PATCH 116/170] 8379394: Confine array dimension setting to the ArrayKlass constructor Reviewed-by: coleenp, ayang --- src/hotspot/share/oops/arrayKlass.cpp | 6 +++--- src/hotspot/share/oops/arrayKlass.hpp | 5 ++--- src/hotspot/share/oops/objArrayKlass.cpp | 3 +-- src/hotspot/share/oops/typeArrayKlass.cpp | 2 +- src/hotspot/share/runtime/vmStructs.cpp | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/oops/arrayKlass.cpp b/src/hotspot/share/oops/arrayKlass.cpp index 30a2bc5102a..8a73f58b46a 100644 --- a/src/hotspot/share/oops/arrayKlass.cpp +++ b/src/hotspot/share/oops/arrayKlass.cpp @@ -41,7 +41,7 @@ #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" -ArrayKlass::ArrayKlass() { +ArrayKlass::ArrayKlass() : _dimension() { assert(CDSConfig::is_dumping_static_archive() || CDSConfig::is_using_archive(), "only for CDS"); } @@ -88,9 +88,9 @@ Method* ArrayKlass::uncached_lookup_method(const Symbol* name, return super()->uncached_lookup_method(name, signature, OverpassLookupMode::skip, private_mode); } -ArrayKlass::ArrayKlass(Symbol* name, KlassKind kind) : +ArrayKlass::ArrayKlass(int n, Symbol* name, KlassKind kind) : Klass(kind), - _dimension(1), + _dimension(n), _higher_dimension(nullptr), _lower_dimension(nullptr) { // Arrays don't add any new methods, so their vtable is the same size as diff --git a/src/hotspot/share/oops/arrayKlass.hpp b/src/hotspot/share/oops/arrayKlass.hpp index b9b100f18a8..738387c57b4 100644 --- a/src/hotspot/share/oops/arrayKlass.hpp +++ b/src/hotspot/share/oops/arrayKlass.hpp @@ -38,7 +38,7 @@ class ArrayKlass: public Klass { private: // If you add a new field that points to any metaspace object, you // must add this field to ArrayKlass::metaspace_pointers_do(). - int _dimension; // This is n'th-dimensional array. + const int _dimension; // This is n'th-dimensional array. ObjArrayKlass* volatile _higher_dimension; // Refers the (n+1)'th-dimensional array (if present). ArrayKlass* volatile _lower_dimension; // Refers the (n-1)'th-dimensional array (if present). @@ -46,7 +46,7 @@ class ArrayKlass: public Klass { // Constructors // The constructor with the Symbol argument does the real array // initialization, the other is a dummy - ArrayKlass(Symbol* name, KlassKind kind); + ArrayKlass(int n, Symbol* name, KlassKind kind); ArrayKlass(); public: @@ -63,7 +63,6 @@ class ArrayKlass: public Klass { // Instance variables int dimension() const { return _dimension; } - void set_dimension(int dimension) { _dimension = dimension; } ObjArrayKlass* higher_dimension() const { return _higher_dimension; } inline ObjArrayKlass* higher_dimension_acquire() const; // load with acquire semantics diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp index 2bbe898adbd..fccd02f14e6 100644 --- a/src/hotspot/share/oops/objArrayKlass.cpp +++ b/src/hotspot/share/oops/objArrayKlass.cpp @@ -120,8 +120,7 @@ ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_da return oak; } -ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, Kind) { - set_dimension(n); +ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(n, name, Kind) { set_element_klass(element_klass); Klass* bk; diff --git a/src/hotspot/share/oops/typeArrayKlass.cpp b/src/hotspot/share/oops/typeArrayKlass.cpp index bdf37c7db49..7dbea9ce475 100644 --- a/src/hotspot/share/oops/typeArrayKlass.cpp +++ b/src/hotspot/share/oops/typeArrayKlass.cpp @@ -78,7 +78,7 @@ u2 TypeArrayKlass::compute_modifier_flags() const { return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; } -TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name, Kind) { +TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(1, name, Kind) { set_layout_helper(array_layout_helper(type)); assert(is_array_klass(), "sanity"); assert(is_typeArray_klass(), "sanity"); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index a54fbc7e8ab..9796b990b2a 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -166,7 +166,7 @@ volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \ volatile_nonstatic_field(oopDesc, _metadata._compressed_klass, narrowKlass) \ static_field(BarrierSet, _barrier_set, BarrierSet*) \ - nonstatic_field(ArrayKlass, _dimension, int) \ + nonstatic_field(ArrayKlass, _dimension, const int) \ volatile_nonstatic_field(ArrayKlass, _higher_dimension, ObjArrayKlass*) \ volatile_nonstatic_field(ArrayKlass, _lower_dimension, ArrayKlass*) \ nonstatic_field(BSMAttributeEntries, _offsets, Array*) \ From ba0708caddc70d5567dc20c3c58ddae6c275de4d Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Mon, 9 Mar 2026 12:08:14 +0000 Subject: [PATCH 117/170] 8379331: Remove modular transition support settings from TEST.ROOT files Reviewed-by: jvernee, alanb --- test/docs/TEST.ROOT | 5 ----- test/hotspot/jtreg/TEST.ROOT | 5 ----- test/jaxp/TEST.ROOT | 5 ----- test/jdk/TEST.ROOT | 5 ----- test/langtools/TEST.ROOT | 5 ----- 5 files changed, 25 deletions(-) diff --git a/test/docs/TEST.ROOT b/test/docs/TEST.ROOT index 9a7e66b631c..11cba9c1c88 100644 --- a/test/docs/TEST.ROOT +++ b/test/docs/TEST.ROOT @@ -40,11 +40,6 @@ groups=TEST.groups # Minimum jtreg version requiredVersion=8.2.1+1 -# Use new module options -useNewOptions=true - -# Use --patch-module instead of -Xmodule: -useNewPatchModule=true # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index d1c72b9768c..2a3d3eebbbd 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -113,8 +113,3 @@ requiredVersion=8.2.1+1 # does not need ../../../ notation to reach them external.lib.roots = ../../../ -# Use new module options -useNewOptions=true - -# Use --patch-module instead of -Xmodule: -useNewPatchModule=true diff --git a/test/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT index aff3b769830..ddf29839e20 100644 --- a/test/jaxp/TEST.ROOT +++ b/test/jaxp/TEST.ROOT @@ -29,8 +29,3 @@ requiredVersion=8.2.1+1 # does not need ../../ notation to reach them external.lib.roots = ../../ -# Use new module options -useNewOptions=true - -# Use --patch-module instead of -Xmodule: -useNewPatchModule=true diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index cc571deab20..0e339d29cea 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -129,8 +129,3 @@ requiredVersion=8.2.1+1 # does not need ../../ notation to reach them external.lib.roots = ../../ -# Use new module options -useNewOptions=true - -# Use --patch-module instead of -Xmodule: -useNewPatchModule=true diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index 434cf91b0ec..c76f99d1396 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -17,11 +17,6 @@ groups=TEST.groups # Minimum jtreg version requiredVersion=8.2.1+1 -# Use new module options -useNewOptions=true - -# Use --patch-module instead of -Xmodule: -useNewPatchModule=true # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them From 82430a7666f7ad876c023699d91947d127dd5db3 Mon Sep 17 00:00:00 2001 From: Maksim Gaidideev Date: Mon, 9 Mar 2026 12:46:43 +0000 Subject: [PATCH 118/170] 8360121: Add -XX:+StressLoopPeeling to CTW Reviewed-by: mchevalier, chagedorn --- .../testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index 11694f72837..d9facb13078 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -319,6 +319,7 @@ public class CtwRunner { "-XX:+StressGCM", "-XX:+StressIGVN", "-XX:+StressCCP", + "-XX:+StressLoopPeeling", "-XX:+StressMacroExpansion", "-XX:+StressMacroElimination", "-XX:+StressIncrementalInlining", From e018cd60a09c37a1be749e7b45c25022e02f81c7 Mon Sep 17 00:00:00 2001 From: David Beaumont Date: Mon, 9 Mar 2026 13:07:10 +0000 Subject: [PATCH 119/170] 8379441: Refactor jaxp/javax catalog tests to use JUnit Reviewed-by: joehw, dfuchs --- .../catalog/CatalogReferCircularityTest.java | 39 ++++++------ .../catalog/DefaultFeaturesTest.java | 32 +++------- .../functional/catalog/DeferFeatureTest.java | 63 +++++++++---------- .../catalog/DelegatePublicTest.java | 26 ++++---- .../catalog/DelegateSystemTest.java | 26 ++++---- .../functional/catalog/DelegateUriTest.java | 28 ++++----- .../jaxp/functional/catalog/GroupTest.java | 32 +++++----- .../functional/catalog/LoadCatalogTest.java | 46 +++++++------- .../functional/catalog/NextCatalogTest.java | 34 +++++----- .../functional/catalog/NormalizationTest.java | 31 ++++----- .../functional/catalog/PreferFeatureTest.java | 30 ++++----- .../jaxp/functional/catalog/PreferTest.java | 18 +++--- .../functional/catalog/PublicFamilyTest.java | 19 +++--- .../jaxp/functional/catalog/PublicTest.java | 28 +++++---- .../catalog/ResolveFeatureTest.java | 39 +++++++----- .../functional/catalog/RewriteSystemTest.java | 26 ++++---- .../functional/catalog/RewriteUriTest.java | 28 +++++---- .../catalog/SpecifyCatalogTest.java | 24 ++++--- .../functional/catalog/SystemFamilyTest.java | 26 ++++---- .../functional/catalog/SystemSuffixTest.java | 26 ++++---- .../jaxp/functional/catalog/SystemTest.java | 28 +++++---- .../functional/catalog/UriFamilyTest.java | 28 +++++---- .../functional/catalog/UriSuffixTest.java | 28 +++++---- .../xml/jaxp/functional/catalog/UriTest.java | 30 ++++----- .../functional/catalog/UrnUnwrappingTest.java | 18 +++--- .../catalog/ValidateCatalogTest.java | 27 ++++---- .../jaxp/libs/catalog/CatalogTestUtils.java | 16 ++--- .../jaxp/libs/catalog/ResolutionChecker.java | 52 ++++----------- 28 files changed, 412 insertions(+), 436 deletions(-) diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/CatalogReferCircularityTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/CatalogReferCircularityTest.java index 0447270d99a..c88827c1a39 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/CatalogReferCircularityTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/CatalogReferCircularityTest.java @@ -23,18 +23,20 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.CatalogReferCircularityTest + * @run junit/othervm catalog.CatalogReferCircularityTest * @summary Via nextCatalog entry, the catalog reference chain may be * a (partial) closed circuit. For instance, a catalog may use itself * as an additional catalog specified in its own nextCatalog entry. @@ -42,22 +44,19 @@ import org.testng.annotations.Test; */ public class CatalogReferCircularityTest { - @Test(dataProvider = "catalogName", - expectedExceptions = CatalogException.class) + @ParameterizedTest + @ValueSource(strings={ + // This catalog defines itself as next catalog. + "catalogReferCircle-itself.xml", + + // This catalog defines catalogReferCircle-right.xml as its next + // catalog. And catalogReferCircle-right.xml also defines + // catalogReferCircle-left.xml as its next catalog, too. + "catalogReferCircle-left.xml" }) public void testReferCircularity(String catalogFile) { - catalogResolver(catalogFile).resolveEntity(null, - "http://remote/dtd/ghost/docGhost.dtd"); - } - - @DataProvider(name = "catalogName") - public Object[][] catalogName() { - return new Object[][] { - // This catalog defines itself as next catalog. - { "catalogReferCircle-itself.xml" }, - - // This catalog defines catalogReferCircle-right.xml as its next - // catalog. And catalogReferCircle-right.xml also defines - // catalogReferCircle-left.xml as its next catalog, too. - { "catalogReferCircle-left.xml" } }; + CatalogResolver resolver = catalogResolver(catalogFile); + Assertions.assertThrows( + CatalogException.class, + () -> resolver.resolveEntity(null, "http://remote/dtd/ghost/docGhost.dtd")); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/DefaultFeaturesTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/DefaultFeaturesTest.java index d76b56d7510..f17aa04ac76 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/DefaultFeaturesTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/DefaultFeaturesTest.java @@ -23,42 +23,30 @@ package catalog; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogFeatures.Feature; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.DefaultFeaturesTest + * @run junit/othervm catalog.DefaultFeaturesTest * @summary This case tests if the default feature values are expected. */ public class DefaultFeaturesTest { - - private CatalogFeatures defaultFeature; - - @BeforeClass - public void init() { - defaultFeature = CatalogFeatures.defaults(); - } - - @Test(dataProvider="feature-value") + @ParameterizedTest + @MethodSource("defaultFeaturesData") public void testDefaultFeatures(Feature feature, String expected) { - String featureValue = defaultFeature.get(feature); - if (expected != null) { - Assert.assertEquals(featureValue, expected); - } else { - Assert.assertNull(featureValue); - } + CatalogFeatures defaultFeature = CatalogFeatures.defaults(); + assertEquals(expected, defaultFeature.get(feature)); } - @DataProvider(name = "feature-value") - public Object[][] data() { + public static Object[][] defaultFeaturesData() { return new Object[][] { { Feature.FILES, null }, { Feature.PREFER, CatalogTestUtils.PREFER_PUBLIC }, diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java index 2d5771557ad..36335cb586d 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/DeferFeatureTest.java @@ -23,42 +23,43 @@ package catalog; -import static catalog.CatalogTestUtils.DEFER_FALSE; -import static catalog.CatalogTestUtils.DEFER_TRUE; -import static catalog.CatalogTestUtils.getCatalogPath; -import static javax.xml.catalog.CatalogFeatures.Feature.DEFER; - -import java.lang.reflect.Method; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.Catalog; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogManager; import javax.xml.catalog.CatalogResolver; +import java.lang.reflect.Method; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.DEFER_FALSE; +import static catalog.CatalogTestUtils.DEFER_TRUE; +import static catalog.CatalogTestUtils.getCatalogPath; +import static javax.xml.catalog.CatalogFeatures.Feature.DEFER; +import static org.junit.jupiter.api.Assertions.assertEquals; /* * @test * @bug 8077931 8176405 * @library /javax/xml/jaxp/libs * @modules java.xml/javax.xml.catalog:open - * @run testng/othervm catalog.DeferFeatureTest + * @run junit/othervm catalog.DeferFeatureTest * @summary This case tests whether the catalogs specified in delegateSystem, * delegatePublic, delegateURI and nextCatalog entries are used lazily * in resolution via defer feature. */ public class DeferFeatureTest { - @Test(dataProvider = "catalog-countOfLoadedCatalogFile") + @ParameterizedTest + @MethodSource("deferData") public void testDeferFeature(Catalog catalog, int catalogCount) throws Exception { - Assert.assertEquals(loadedCatalogCount(catalog), catalogCount); + assertEquals(catalogCount, loadedCatalogCount(catalog)); } - @Test(dataProvider = "testDeferFeatureByResolve") + @ParameterizedTest + @MethodSource("deferByResolveData") public void testDeferFeatureByResolve(Catalog catalog, int catalogCount) throws Exception { CatalogResolver cr = createResolver(catalog); @@ -67,41 +68,39 @@ public class DeferFeatureTest { cr.resolveEntity("-//REMOTE//DTD ALICE DOCALICE", "http://remote/dtd/alice/"); } catch (CatalogException ce) {} - Assert.assertEquals(loadedCatalogCount(catalog), catalogCount); + assertEquals(catalogCount, loadedCatalogCount(catalog)); } - @DataProvider(name = "catalog-countOfLoadedCatalogFile") - public Object[][] data() { - return new Object[][]{ - // By default, alternative catalogs are not loaded. - {createCatalog(CatalogFeatures.defaults()), 1}, - // Alternative catalogs are not loaded when DEFER is set to true. - {createCatalog(createDeferFeature(DEFER_TRUE)), 1}, - // The 3 alternative catalogs are pre-loaded along with the parent - //when DEFER is set to false. - {createCatalog(createDeferFeature(DEFER_FALSE)), 4}}; + public static Object[][] deferData() { + return new Object[][] { + // By default, alternative catalogs are not loaded. + { createCatalog(CatalogFeatures.defaults()), 1 }, + // Alternative catalogs are not loaded when DEFER is set to true. + { createCatalog(createDeferFeature(DEFER_TRUE)), 1 }, + // The 3 alternative catalogs are pre-loaded along with the parent + //when DEFER is set to false. + { createCatalog(createDeferFeature(DEFER_FALSE)), 4 } }; } - @DataProvider(name = "testDeferFeatureByResolve") - public Object[][] getData() { - return new Object[][]{ - {createCatalog(createDeferFeature(DEFER_TRUE)), 4} + public static Object[][] deferByResolveData() { + return new Object[][] { + { createCatalog(createDeferFeature(DEFER_TRUE)), 4 } }; } - private CatalogFeatures createDeferFeature(String defer) { + private static CatalogFeatures createDeferFeature(String defer) { return CatalogFeatures.builder().with(DEFER, defer).build(); } - private Catalog createCatalog(CatalogFeatures feature) { + private static Catalog createCatalog(CatalogFeatures feature) { return CatalogManager.catalog(feature, getCatalogPath("deferFeature.xml")); } - private CatalogResolver createResolver(Catalog catalog) { + private static CatalogResolver createResolver(Catalog catalog) { return CatalogManager.catalogResolver(catalog); } - private int loadedCatalogCount(Catalog catalog) throws Exception { + private static int loadedCatalogCount(Catalog catalog) throws Exception { Method method = catalog.getClass().getDeclaredMethod("loadedCatalogCount"); method.setAccessible(true); return (int) method.invoke(catalog); diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/DelegatePublicTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/DelegatePublicTest.java index 43c6bf42f44..579140825c2 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/DelegatePublicTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/DelegatePublicTest.java @@ -23,32 +23,32 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkPubIdResolution; -import static catalog.ResolutionChecker.expectExceptionOnPubId; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkPubIdResolution; +import static catalog.ResolutionChecker.expectExceptionOnPubId; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.DelegatePublicTest + * @run junit/othervm catalog.DelegatePublicTest * @summary Get matched URIs from DelegatePublic entries. */ public class DelegatePublicTest { - @Test(dataProvider = "publicId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String publicId, String matchedUri) { checkPubIdResolution(createResolver(), publicId, matchedUri); } - @DataProvider(name = "publicId-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified public id is defined in // a delegate catalog file of the current catalog file. @@ -71,15 +71,15 @@ public class DelegatePublicTest { "http://local/base/dtd/carl/docCarlPub.dtd" } }; } - @Test(dataProvider = "publicId-expectedExceptionClass") + @ParameterizedTest + @MethodSource("dataOnException") public void testException(String publicId, Class expectedExceptionClass) { expectExceptionOnPubId(createResolver(), publicId, expectedExceptionClass); } - @DataProvider(name = "publicId-expectedExceptionClass") - public Object[][] dataOnException() { + public static Object[][] dataOnException() { return new Object[][] { // The matched delegatePublic entry of the specified public id // defines a non-existing delegate catalog file. That should @@ -93,7 +93,7 @@ public class DelegatePublicTest { CatalogException.class } }; } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("delegatePublic.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateSystemTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateSystemTest.java index 554d23776f9..27da1105b2c 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateSystemTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateSystemTest.java @@ -23,32 +23,32 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkSysIdResolution; -import static catalog.ResolutionChecker.expectExceptionOnSysId; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkSysIdResolution; +import static catalog.ResolutionChecker.expectExceptionOnSysId; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.DelegateSystemTest + * @run junit/othervm catalog.DelegateSystemTest * @summary Get matched URIs from delegateSystem entries. */ public class DelegateSystemTest { - @Test(dataProvider = "systemId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String systemId, String matchedUri) { checkSysIdResolution(createResolver(), systemId, matchedUri); } - @DataProvider(name = "systemId-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified system id is defined in // a delegate catalog file of the current catalog file. @@ -71,15 +71,15 @@ public class DelegateSystemTest { "http://local/base/dtd/carl/docCarlDS.dtd"} }; } - @Test(dataProvider = "systemId-expectedExceptionClass") + @ParameterizedTest + @MethodSource("dataOnException") public void testException(String systemId, Class expectedExceptionClass) { expectExceptionOnSysId(createResolver(), systemId, expectedExceptionClass); } - @DataProvider(name = "systemId-expectedExceptionClass") - public Object[][] dataOnException() { + public static Object[][] dataOnException() { return new Object[][] { // The matched delegateSystem entry of the specified system id // defines a non-existing delegate catalog file. That should @@ -93,7 +93,7 @@ public class DelegateSystemTest { CatalogException.class } }; } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("delegateSystem.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateUriTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateUriTest.java index 2a92149a730..0175a99f938 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateUriTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/DelegateUriTest.java @@ -23,32 +23,32 @@ package catalog; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkUriResolution; import static catalog.ResolutionChecker.expectExceptionOnUri; -import javax.xml.catalog.CatalogResolver; -import javax.xml.catalog.CatalogException; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.DelegateUriTest + * @run junit/othervm catalog.DelegateUriTest * @summary Get matched URIs from delegateURI entries. */ public class DelegateUriTest { - @Test(dataProvider = "uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String uri, String matchedUri) { checkUriResolution(createResolver(), uri, matchedUri); } - @DataProvider(name = "uri-matchedUri") - public Object[][] data() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified URI reference is defined in // a delegate catalog file of the current catalog file. @@ -71,14 +71,14 @@ public class DelegateUriTest { "http://local/base/dtd/carl/docCarlDU.dtd"} }; } - @Test(dataProvider = "uri-expectedExceptionClass") + @ParameterizedTest + @MethodSource("dataOnException") public void testException(String uri, Class expectedExceptionClass) { expectExceptionOnUri(createResolver(), uri, expectedExceptionClass); } - @DataProvider(name = "uri-expectedExceptionClass") - public Object[][] dataOnException() { + public static Object[][] dataOnException() { return new Object[][] { // The matched delegateURI entry of the specified URI reference // defines a non-existing delegate catalog file. That should @@ -92,7 +92,7 @@ public class DelegateUriTest { CatalogException.class } }; } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogUriResolver("delegateUri.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/GroupTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/GroupTest.java index 7516be7d560..37910c2b1f5 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/GroupTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/GroupTest.java @@ -23,22 +23,22 @@ package catalog; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.catalogResolver; import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkPubIdResolution; import static catalog.ResolutionChecker.checkSysIdResolution; import static catalog.ResolutionChecker.checkUriResolution; -import javax.xml.catalog.CatalogResolver; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.GroupTest + * @run junit/othervm catalog.GroupTest * @summary Get matched URIs from system, public and uri entries respectively, * and some of the entries are enclosed by group entries. */ @@ -46,13 +46,13 @@ public class GroupTest { private static final String CATALOG_GROUP = "group.xml"; - @Test(dataProvider = "systemId-matchedUri") + @ParameterizedTest + @MethodSource("dataMatchSysId") public void testMatchOnSysId(String uri, String matchedUri) { checkSysIdResolution(createResolver(), uri, matchedUri); } - @DataProvider(name = "systemId-matchedUri") - public Object[][] dataOnSysId() { + public static Object[][] dataMatchSysId() { return new Object[][] { // The matched URI of the specified system id is enclosed by a // group entry. @@ -72,13 +72,13 @@ public class GroupTest { "http://local/base/dtd/docCarlSys1.dtd" } }; } - @Test(dataProvider = "publicId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatchPubId") public void testMatchOnPubId(String uri, String matchedUri) { checkPubIdResolution(createResolver(), uri, matchedUri); } - @DataProvider(name = "publicId-matchedUri") - public Object[][] dataOnPubId() { + public static Object[][] dataOnMatchPubId() { return new Object[][] { // The matched URI of the specified public id is enclosed by a // group entry. @@ -98,13 +98,13 @@ public class GroupTest { "http://local/base/dtd/docCarlPub1.dtd" } }; } - @Test(dataProvider = "uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatchUri") public void testMatchOnUri(String uri, String matchedUri) { checkUriResolution(catalogUriResolver(CATALOG_GROUP), uri, matchedUri); } - @DataProvider(name = "uri-matchedUri") - public Object[][] dataOnUri() { + public static Object[][] dataOnMatchUri() { return new Object[][] { // The matched URI of the specified URI reference is enclosed by // a group entry. @@ -124,7 +124,7 @@ public class GroupTest { "http://local/base/dtd/docAliceURI.dtd" } }; } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver(CATALOG_GROUP); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/LoadCatalogTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/LoadCatalogTest.java index 6a5248b8f9f..481c2fa1f83 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/LoadCatalogTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/LoadCatalogTest.java @@ -23,6 +23,12 @@ package catalog; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.CATALOG_PUBLIC; import static catalog.CatalogTestUtils.CATALOG_SYSTEM; import static catalog.CatalogTestUtils.CATALOG_URI; @@ -30,18 +36,13 @@ import static catalog.CatalogTestUtils.catalogResolver; import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkSysIdResolution; import static catalog.ResolutionChecker.checkUriResolution; - -import javax.xml.catalog.CatalogException; -import javax.xml.catalog.CatalogResolver; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.LoadCatalogTest + * @run junit/othervm catalog.LoadCatalogTest * @summary When catalog resolver loads catalog files, the current catalog file * and the catalog files specified by the nextCatalog entries may not * accessible. This case tests how does the resolver handle this issue. @@ -55,14 +56,14 @@ public class LoadCatalogTest { private static final String ID_ALICE_URI = "http://remote/dtd/uri/alice/docAlice.dtd"; private static final String ID_DUMMY = "http://remote/dtd/doc.dtd"; - @Test(dataProvider = "entityResolver") + @ParameterizedTest + @MethodSource("entityResolver") public void testMatchOnEntityResolver(CatalogResolver resolver) { checkSysIdResolution(resolver, ID_ALICE, "http://local/dtd/docAliceSys.dtd"); } - @DataProvider(name = "entityResolver") - public Object[][] entityResolver() { + public static Object[][] entityResolver() { return new Object[][] { // This EntityResolver loads multiple catalog files one by one. // All of the files are available. @@ -75,14 +76,14 @@ public class LoadCatalogTest { CATALOG_SYSTEM) } }; } - @Test(dataProvider = "uriResolver") + @ParameterizedTest + @MethodSource("uriResolver") public void testMatchOnUriResolver(CatalogResolver resolver) { checkUriResolution(resolver, ID_ALICE_URI, "http://local/dtd/docAliceURI.dtd"); } - @DataProvider(name = "uriResolver") - public Object[][] uriResolver() { + public static Object[][] uriResolver() { return new Object[][] { // This URIResolver loads multiple catalog files one by one. // All of the files are available. @@ -95,20 +96,21 @@ public class LoadCatalogTest { CATALOG_URI) } }; } - @Test(dataProvider = "catalogName", - expectedExceptions = CatalogException.class) - public void testExceptionOnEntityResolver(String[] catalogName) { - catalogResolver(catalogName).resolveEntity(null, ID_DUMMY); + @ParameterizedTest + @MethodSource("catalogName") + public void testException(String[] catalogName) { + CatalogResolver resolver = catalogResolver(catalogName); + assertThrows(CatalogException.class, () -> resolver.resolveEntity(null, ID_DUMMY)); } - @Test(dataProvider = "catalogName", - expectedExceptions = CatalogException.class) + @ParameterizedTest + @MethodSource("catalogName") public void testExceptionOnUriResolver(String[] catalogName) { - catalogUriResolver(catalogName).resolve(ID_DUMMY, null); + CatalogResolver resolver = catalogUriResolver(catalogName); + assertThrows(CatalogException.class, () -> resolver.resolve(ID_DUMMY, null)); } - @DataProvider(name = "catalogName") - public Object[][] catalogName() { + public static Object[][] catalogName() { return new Object[][] { // This catalog file set includes null catalog files. { (String[]) null }, diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/NextCatalogTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/NextCatalogTest.java index d7e0711636d..ff56b86a500 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/NextCatalogTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/NextCatalogTest.java @@ -23,22 +23,22 @@ package catalog; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.catalogResolver; import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkPubIdResolution; import static catalog.ResolutionChecker.checkSysIdResolution; import static catalog.ResolutionChecker.checkUriResolution; -import javax.xml.catalog.CatalogResolver; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.NextCatalogTest + * @run junit/othervm catalog.NextCatalogTest * @summary Get matched URIs from system, public and uri entries respectively, * but some of the entries are defined in none-current catalog files. */ @@ -49,13 +49,13 @@ public class NextCatalogTest { private static final String CATALOG_NEXTCATALOGRIGHT = "nextCatalog-right.xml"; - @Test(dataProvider = "systemId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnSysId") public void testNextCatalogOnSysId(String sytemId, String matchedUri) { checkSysIdResolution(createEntityResolver(), sytemId, matchedUri); } - @DataProvider(name = "systemId-matchedUri") - public Object[][] dataOnSysId() { + public static Object[][] dataOnSysId() { return new Object[][] { // This matched URI of the specified system id is defined in a // next catalog file. @@ -81,13 +81,13 @@ public class NextCatalogTest { "http://local/base/dtd/docDuplicateLeftSys.dtd" } }; } - @Test(dataProvider = "publicId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnPubId") public void testNextCatalogOnPubId(String publicId, String matchedUri) { checkPubIdResolution(createEntityResolver(), publicId, matchedUri); } - @DataProvider(name = "publicId-matchedUri") - public Object[][] dataOnPubId() { + public static Object[][] dataOnPubId() { return new Object[][] { // This matched URI of the specified public id is defined in a // next catalog file. @@ -113,13 +113,13 @@ public class NextCatalogTest { "http://local/base/dtd/docDuplicateLeftPub.dtd" } }; } - @Test(dataProvider = "uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnUri") public void testNextCatalogOnUri(String uri, String matchedUri) { checkUriResolution(createUriResolver(), uri, matchedUri); } - @DataProvider(name = "uri-matchedUri") - public Object[][] dataOnUri() { + public static Object[][] dataOnUri() { return new Object[][] { // This matched URI of the specified URI reference is defined in // a next catalog file. @@ -145,12 +145,12 @@ public class NextCatalogTest { "http://local/base/dtd/docDuplicateLeftURI.dtd" } }; } - private CatalogResolver createEntityResolver() { + private static CatalogResolver createEntityResolver() { return catalogResolver(CATALOG_NEXTCATALOGLEFT, CATALOG_NEXTCATALOGRIGHT); } - private CatalogResolver createUriResolver() { + private static CatalogResolver createUriResolver() { return catalogUriResolver(CATALOG_NEXTCATALOGLEFT, CATALOG_NEXTCATALOGRIGHT); } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/NormalizationTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/NormalizationTest.java index 74fc25e90c1..0a112fd7426 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/NormalizationTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/NormalizationTest.java @@ -23,22 +23,22 @@ package catalog; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.catalogResolver; import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkPubIdResolution; import static catalog.ResolutionChecker.checkSysIdResolution; import static catalog.ResolutionChecker.checkUriResolution; -import javax.xml.catalog.CatalogResolver; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.NormalizationTest + * @run junit/othervm catalog.NormalizationTest * @summary Before matching identifiers and URI references, it has to normalize * the passed identifiers and URI references. And then the catalog * resolver uses the normalized stuff to search the counterparts in @@ -48,23 +48,25 @@ public class NormalizationTest { private static final String CATALOG_NORMALIZATION = "normalization.xml"; - @Test(dataProvider = "systemId_uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnSysIdAndUri") public void testNormalizationOnSysId(String sytemId, String matchedUri) { checkSysIdResolution(createEntityResolver(), sytemId, matchedUri); } - @Test(dataProvider = "publicId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnPubId") public void testNormalizationOnPubId(String publicId, String matchedUri) { checkPubIdResolution(createEntityResolver(), publicId, matchedUri); } - @Test(dataProvider = "systemId_uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnSysIdAndUri") public void testNormalizationOnUri(String uri, String matchedUri) { checkUriResolution(createUriResolver(), uri, matchedUri); } - @DataProvider(name = "systemId_uri-matchedUri") - public Object[][] dataOnSysIdAndUri() { + public static Object[][] dataOnSysIdAndUri() { return new Object[][] { // The specified system id/URI reference contains spaces. And // the counterparts in system/uri entries also contain spaces. @@ -85,8 +87,7 @@ public class NormalizationTest { "http://local/base/dtd/docBobSys.dtd" } }; } - @DataProvider(name = "publicId-matchedUri") - public Object[][] dataOnPubId() { + public static Object[][] dataOnPubId() { return new Object[][] { // The specified public id contains spaces. And the counterparts // in public entry also contains spaces. @@ -103,11 +104,11 @@ public class NormalizationTest { "http://local/base/dtd/docBobPub.dtd" } }; } - private CatalogResolver createEntityResolver() { + private static CatalogResolver createEntityResolver() { return catalogResolver(CATALOG_NORMALIZATION); } - private CatalogResolver createUriResolver() { + private static CatalogResolver createUriResolver() { return catalogUriResolver(CATALOG_NORMALIZATION); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/PreferFeatureTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/PreferFeatureTest.java index 85cb2505244..4f9cfcd1f82 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/PreferFeatureTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/PreferFeatureTest.java @@ -23,38 +23,38 @@ package catalog; -import static catalog.CatalogTestUtils.PREFER_PUBLIC; -import static catalog.CatalogTestUtils.PREFER_SYSTEM; -import static catalog.CatalogTestUtils.catalogResolver; -import static javax.xml.catalog.CatalogFeatures.Feature.PREFER; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.PREFER_PUBLIC; +import static catalog.CatalogTestUtils.PREFER_SYSTEM; +import static catalog.CatalogTestUtils.catalogResolver; +import static javax.xml.catalog.CatalogFeatures.Feature.PREFER; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.PreferFeatureTest + * @run junit/othervm catalog.PreferFeatureTest * @summary This case tests how does the feature affect the catalog resolution, * and tests the priority between this feature and attribute prefer * in catalog file. */ public class PreferFeatureTest { - @Test(dataProvider = "prefer-publicId-systemId", - expectedExceptions = CatalogException.class) - public void testPreferFeature(String prefer, String systemId, - String publicId) { - createResolver(prefer).resolveEntity(systemId, publicId); + @ParameterizedTest + @MethodSource("data") + public void testPreferFeature(String prefer, String systemId, String publicId) { + CatalogResolver resolver = createResolver(prefer); + assertThrows(CatalogException.class, () -> resolver.resolveEntity(systemId, publicId)); } - @DataProvider(name = "prefer-publicId-systemId") - public Object[][] data() { + public static Object[][] data() { return new Object[][] { // The feature prefer is system. There's a match for the // specified public id, and no match for the specified system id. @@ -72,7 +72,7 @@ public class PreferFeatureTest { "http://remote/dtd/bob/docBobDummy.dtd"} }; } - private CatalogResolver createResolver(String prefer) { + private static CatalogResolver createResolver(String prefer) { return catalogResolver( CatalogFeatures.builder().with(PREFER, prefer).build(), "preferFeature.xml"); diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/PreferTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/PreferTest.java index 6bcbd140466..c358ff85c62 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/PreferTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/PreferTest.java @@ -23,19 +23,19 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkExtIdResolution; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkExtIdResolution; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.PreferTest + * @run junit/othervm catalog.PreferTest * @summary Get matched URIs from system and public family entries, which * specify the prefer attribute. It tests how does the prefer attribute * affect the resolution procedure. The test rule is based on OASIS @@ -43,14 +43,14 @@ import org.testng.annotations.Test; */ public class PreferTest { - @Test(dataProvider = "publicId-systemId-matchedUri") + @ParameterizedTest + @MethodSource("data") public void testPrefer(String publicId, String systemId, String expected) { checkExtIdResolution(createResolver(), publicId, systemId, expected); } - @DataProvider(name = "publicId-systemId-matchedUri") - public Object[][] data() { + public static Object[][] data() { return new Object[][] { // The prefer attribute is public. Both of the specified public // id and system id have matches in the catalog file. But @@ -85,7 +85,7 @@ public class PreferTest { "http://local/base/dtd/docBobSys.dtd" } }; } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("prefer.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/PublicFamilyTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/PublicFamilyTest.java index 42dc6bbe215..44a0d46537f 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/PublicFamilyTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/PublicFamilyTest.java @@ -23,20 +23,21 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkNoMatch; -import static catalog.ResolutionChecker.checkPubIdResolution; +import org.junit.jupiter.api.Test; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkNoMatch; +import static catalog.ResolutionChecker.checkPubIdResolution; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.PublicFamilyTest + * @run junit/othervm catalog.PublicFamilyTest * @summary Get matched URIs from public and delegatePublic entries. * It tests the resolution priorities among the public family entries. * The test rule is based on OASIS Standard V1.1 section 7.1.2. @@ -58,12 +59,12 @@ public class PublicFamilyTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) - public void testNoMatched() { - checkNoMatch(createResolver()); + @Test + public void testNoMatch() { + assertThrows(CatalogException.class, () -> checkNoMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("publicFamily.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/PublicTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/PublicTest.java index d44dca87732..fe137eac6e9 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/PublicTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/PublicTest.java @@ -23,33 +23,35 @@ package catalog; -import static catalog.CatalogTestUtils.CATALOG_PUBLIC; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkNoMatch; -import static catalog.ResolutionChecker.checkPubIdResolution; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.CATALOG_PUBLIC; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkNoMatch; +import static catalog.ResolutionChecker.checkPubIdResolution; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.PublicTest + * @run junit/othervm catalog.PublicTest * @summary Get matched URIs from public entries. */ public class PublicTest { - @Test(dataProvider = "publicId-matchedUri") + @ParameterizedTest + @MethodSource("data") public void testPublic(String publicId, String matchedUri) { checkPubIdResolution(createResolver(), publicId, matchedUri); } - @DataProvider(name = "publicId-matchedUri") - public Object[][] data() { + public static Object[][] data() { return new Object[][] { // The matched URI of the specified public id is defined in a // public entry. The match is an absolute path. @@ -80,12 +82,12 @@ public class PublicTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver(CATALOG_PUBLIC); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/ResolveFeatureTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/ResolveFeatureTest.java index 0626e83bed9..a642f751a7f 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/ResolveFeatureTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/ResolveFeatureTest.java @@ -23,6 +23,13 @@ package catalog; +import org.junit.jupiter.api.Test; + +import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogFeatures; +import javax.xml.catalog.CatalogFeatures.Feature; +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.CATALOG_SYSTEM; import static catalog.CatalogTestUtils.CATALOG_URI; import static catalog.CatalogTestUtils.RESOLVE_CONTINUE; @@ -33,19 +40,13 @@ import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkSysIdResolution; import static catalog.ResolutionChecker.checkUriResolution; import static javax.xml.catalog.CatalogFeatures.builder; - -import javax.xml.catalog.CatalogException; -import javax.xml.catalog.CatalogFeatures; -import javax.xml.catalog.CatalogFeatures.Feature; -import javax.xml.catalog.CatalogResolver; - -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.ResolveFeatureTest + * @run junit/othervm catalog.ResolveFeatureTest * @summary This case tests how does resolve feature affect the catalog * resolution. */ @@ -55,20 +56,24 @@ public class ResolveFeatureTest { * For strict external identifier resolution, if no match is found, * it should throw CatalogException. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testStrictResolutionOnEntityResolver() { - createEntityResolver(RESOLVE_STRICT).resolveEntity(null, - "http://remote/dtd/alice/docAliceDummy.dtd"); + CatalogResolver resolver = createEntityResolver(RESOLVE_STRICT); + assertThrows( + CatalogException.class, + () -> resolver.resolveEntity(null, "http://remote/dtd/alice/docAliceDummy.dtd")); } /* * For strict URI reference resolution, if no match is found, * it should throw CatalogException. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testStrictResolutionOnUriResolver() { - createUriResolver(RESOLVE_STRICT).resolve( - "http://remote/dtd/alice/docAliceDummy.dtd", null); + CatalogResolver resolver = createUriResolver(RESOLVE_STRICT); + assertThrows( + CatalogException.class, + () -> resolver.resolve("http://remote/dtd/alice/docAliceDummy.dtd", null)); } /* @@ -115,15 +120,15 @@ public class ResolveFeatureTest { "http://remote/dtd/carl/docCarlDummy.dtd", null); } - private CatalogResolver createEntityResolver(String resolve) { + private static CatalogResolver createEntityResolver(String resolve) { return catalogResolver(createFeature(resolve), CATALOG_SYSTEM); } - private CatalogResolver createUriResolver(String resolve) { + private static CatalogResolver createUriResolver(String resolve) { return catalogUriResolver(createFeature(resolve), CATALOG_URI); } - private CatalogFeatures createFeature(String resolve) { + private static CatalogFeatures createFeature(String resolve) { return builder().with(Feature.RESOLVE, resolve).build(); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteSystemTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteSystemTest.java index 647fccd49fb..6c6cc752b98 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteSystemTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteSystemTest.java @@ -23,32 +23,34 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkNoMatch; -import static catalog.ResolutionChecker.checkSysIdResolution; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkNoMatch; +import static catalog.ResolutionChecker.checkSysIdResolution; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.RewriteSystemTest + * @run junit/othervm catalog.RewriteSystemTest * @summary Get matched URIs from rewriteSystem entries. */ public class RewriteSystemTest { - @Test(dataProvider = "systemId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String systemId, String matchedUri) { checkSysIdResolution(createResolver(), systemId, matchedUri); } - @DataProvider(name = "systemId-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified system id is defined in a // rewriteSystem entry. The match is an absolute path. @@ -83,12 +85,12 @@ public class RewriteSystemTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("rewriteSystem.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteUriTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteUriTest.java index d7b98b96f11..1498f866c11 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteUriTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/RewriteUriTest.java @@ -23,32 +23,34 @@ package catalog; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkNoUriMatch; import static catalog.ResolutionChecker.checkUriResolution; - -import javax.xml.catalog.CatalogResolver; -import javax.xml.catalog.CatalogException; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.RewriteUriTest + * @run junit/othervm catalog.RewriteUriTest * @summary Get matched URIs from rewriteURI entries. */ public class RewriteUriTest { - @Test(dataProvider = "uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String uri, String matchedUri) { checkUriResolution(createResolver(), uri, matchedUri); } - @DataProvider(name = "uri-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified URI reference is defined in // a rewriteURI entry. The match is an absolute path. @@ -83,12 +85,12 @@ public class RewriteUriTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoUriMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoUriMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogUriResolver("rewriteUri.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java index 61c59d4049c..d1795f6a45d 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java @@ -23,7 +23,10 @@ package catalog; -import static jaxp.library.JAXPTestUtilities.setSystemProperty; +import org.junit.jupiter.api.Test; + +import javax.xml.catalog.CatalogFeatures; +import javax.xml.catalog.CatalogResolver; import static catalog.CatalogTestUtils.FEATURE_FILES; import static catalog.CatalogTestUtils.catalogResolver; @@ -31,19 +34,14 @@ import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.CatalogTestUtils.getCatalogPath; import static catalog.ResolutionChecker.checkSysIdResolution; import static catalog.ResolutionChecker.checkUriResolution; -import static javax.xml.catalog.CatalogFeatures.builder; import static javax.xml.catalog.CatalogFeatures.Feature.FILES; - -import javax.xml.catalog.CatalogFeatures; -import javax.xml.catalog.CatalogResolver; - -import org.testng.annotations.Test; +import static javax.xml.catalog.CatalogFeatures.builder; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.SpecifyCatalogTest + * @run junit/othervm catalog.SpecifyCatalogTest * @summary This case tests how to specify the catalog files. */ public class SpecifyCatalogTest { @@ -77,7 +75,7 @@ public class SpecifyCatalogTest { */ @Test public void specifyCatalogViaSysProps() { - setSystemProperty(FEATURE_FILES, + System.setProperty(FEATURE_FILES, getCatalogPath("specifyCatalog-sysProps.xml").toASCIIString()); checkResolutionOnEntityResolver(catalogResolver((String[]) null), @@ -93,13 +91,13 @@ public class SpecifyCatalogTest { "http://local/base/dtd/docAPIURI.dtd"); } - private void checkResolutionOnEntityResolver(CatalogResolver resolver, - String matchedUri) { + private static void checkResolutionOnEntityResolver(CatalogResolver resolver, + String matchedUri) { checkSysIdResolution(resolver, ID_SYS, matchedUri); } - private void checkResolutionOnUriResolver(CatalogResolver resolver, - String matchedUri) { + private static void checkResolutionOnUriResolver(CatalogResolver resolver, + String matchedUri) { checkUriResolution(resolver, ID_URI, matchedUri); } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/SystemFamilyTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/SystemFamilyTest.java index ec614332207..927aa65db66 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/SystemFamilyTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/SystemFamilyTest.java @@ -23,21 +23,23 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkNoMatch; -import static catalog.ResolutionChecker.checkSysIdResolution; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkNoMatch; +import static catalog.ResolutionChecker.checkSysIdResolution; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.SystemFamilyTest + * @run junit/othervm catalog.SystemFamilyTest * @summary Get matched URIs from system, rewriteSystem, systemSuffix and * delegateSystem entries. It tests the resolution priorities among * the system family entries. The test rule is based on OASIS @@ -45,13 +47,13 @@ import org.testng.annotations.Test; */ public class SystemFamilyTest { - @Test(dataProvider = "systemId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String systemId, String matchedUri) { checkSysIdResolution(createResolver(), systemId, matchedUri); } - @DataProvider(name = "systemId-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified system id is defined in a // system entry. @@ -72,12 +74,12 @@ public class SystemFamilyTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("systemFamily.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/SystemSuffixTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/SystemSuffixTest.java index 2a40b581654..6890cc2a4c8 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/SystemSuffixTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/SystemSuffixTest.java @@ -23,32 +23,34 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkNoMatch; -import static catalog.ResolutionChecker.checkSysIdResolution; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkNoMatch; +import static catalog.ResolutionChecker.checkSysIdResolution; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.SystemSuffixTest + * @run junit/othervm catalog.SystemSuffixTest * @summary Get matched URIs from systemSuffix entries. */ public class SystemSuffixTest { - @Test(dataProvider = "systemId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String systemId, String matchedUri) { checkSysIdResolution(createResolver(), systemId, matchedUri); } - @DataProvider(name = "systemId-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified system id is defined in a // systemIdSuffix entry. The match is an absolute path. @@ -83,12 +85,12 @@ public class SystemSuffixTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("systemSuffix.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/SystemTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/SystemTest.java index 73c11340b29..53909c4bd5a 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/SystemTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/SystemTest.java @@ -23,33 +23,35 @@ package catalog; -import static catalog.CatalogTestUtils.CATALOG_SYSTEM; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkNoMatch; -import static catalog.ResolutionChecker.checkSysIdResolution; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogException; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.CATALOG_SYSTEM; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkNoMatch; +import static catalog.ResolutionChecker.checkSysIdResolution; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.SystemTest + * @run junit/othervm catalog.SystemTest * @summary Get matched URIs from system entries. */ public class SystemTest { - @Test(dataProvider = "systemId-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String systemId, String matchedUri) { checkSysIdResolution(createResolver(), systemId, matchedUri); } - @DataProvider(name = "systemId-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified system id is defined in a // system entry. The match is an absolute path. @@ -80,12 +82,12 @@ public class SystemTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver(CATALOG_SYSTEM); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/UriFamilyTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/UriFamilyTest.java index 44c9afcfa13..36b8d98ee1f 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/UriFamilyTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/UriFamilyTest.java @@ -23,21 +23,23 @@ package catalog; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkNoUriMatch; import static catalog.ResolutionChecker.checkUriResolution; - -import javax.xml.catalog.CatalogResolver; -import javax.xml.catalog.CatalogException; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.UriFamilyTest + * @run junit/othervm catalog.UriFamilyTest * @summary Get matched URIs from uri, rewriteURI, uriSuffix and delegateURI * entries. It tests the resolution priorities among the uri family * entries. The test rule is based on OASIS Standard V1.1 section @@ -45,13 +47,13 @@ import org.testng.annotations.Test; */ public class UriFamilyTest { - @Test(dataProvider = "uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String systemId, String matchedUri) { checkUriResolution(createResolver(), systemId, matchedUri); } - @DataProvider(name = "uri-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified URI reference is defined in // a uri entry. @@ -72,12 +74,12 @@ public class UriFamilyTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoUriMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoUriMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogUriResolver("uriFamily.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/UriSuffixTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/UriSuffixTest.java index 8feadb03fa2..2bbe63a374a 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/UriSuffixTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/UriSuffixTest.java @@ -23,32 +23,34 @@ package catalog; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkNoUriMatch; import static catalog.ResolutionChecker.checkUriResolution; - -import javax.xml.catalog.CatalogResolver; -import javax.xml.catalog.CatalogException; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.UriSuffixTest + * @run junit/othervm catalog.UriSuffixTest * @summary Get matched URIs from rewriteURI entries. */ public class UriSuffixTest { - @Test(dataProvider = "uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String uri, String matchedUri) { checkUriResolution(createResolver(), uri, matchedUri); } - @DataProvider(name = "uri-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified URI reference is defined in // a uriSuffix entry. The match is an absolute path. @@ -83,12 +85,12 @@ public class UriSuffixTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoUriMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoUriMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogUriResolver("uriSuffix.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/UriTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/UriTest.java index cf76eada5e7..651b2753713 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/UriTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/UriTest.java @@ -23,35 +23,37 @@ package catalog; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.xml.catalog.CatalogException; +import javax.xml.catalog.CatalogFeatures; +import javax.xml.catalog.CatalogResolver; + import static catalog.CatalogTestUtils.CATALOG_URI; import static catalog.CatalogTestUtils.RESOLVE_CONTINUE; import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkNoUriMatch; import static catalog.ResolutionChecker.checkUriResolution; - -import javax.xml.catalog.CatalogResolver; -import javax.xml.catalog.CatalogException; -import javax.xml.catalog.CatalogFeatures; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.UriTest + * @run junit/othervm catalog.UriTest * @summary Get matched URIs from uri entries. */ public class UriTest { - @Test(dataProvider = "uri-matchedUri") + @ParameterizedTest + @MethodSource("dataOnMatch") public void testMatch(String uri, String matchedUri) { checkUriResolution(createResolver(), uri, matchedUri); } - @DataProvider(name = "uri-matchedUri") - public Object[][] dataOnMatch() { + public static Object[][] dataOnMatch() { return new Object[][] { // The matched URI of the specified URI reference is defined in // a uri entry. The match is an absolute path. @@ -92,12 +94,12 @@ public class UriTest { /* * If no match is found, a CatalogException should be thrown. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void testNoMatch() { - checkNoUriMatch(createResolver()); + assertThrows(CatalogException.class, () -> checkNoUriMatch(createResolver())); } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogUriResolver(CATALOG_URI); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/UrnUnwrappingTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/UrnUnwrappingTest.java index f3b99074e98..765e315bd6e 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/UrnUnwrappingTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/UrnUnwrappingTest.java @@ -23,32 +23,32 @@ package catalog; -import static catalog.CatalogTestUtils.catalogResolver; -import static catalog.ResolutionChecker.checkPubIdResolution; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.xml.catalog.CatalogResolver; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static catalog.CatalogTestUtils.catalogResolver; +import static catalog.ResolutionChecker.checkPubIdResolution; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.UrnUnwrappingTest + * @run junit/othervm catalog.UrnUnwrappingTest * @summary If the passed public identifier is started with "urn:publicid:", * it has to be regarded as URN and normalized. And then the catalog * resolver uses the normalized stuff to do matching. */ public class UrnUnwrappingTest { - @Test(dataProvider = "urn-matchedUri") + @ParameterizedTest + @MethodSource("data") public void testUnwrapping(String urn, String matchedUri) { checkPubIdResolution(createResolver(), urn, matchedUri); } - @DataProvider(name = "urn-matchedUri") - public Object[][] data() { + public static Object[][] data() { return new Object[][] { // The specified public id is URN format. { "urn:publicid:-:REMOTE:DTD+ALICE+DOCALICE+XML:EN", @@ -60,7 +60,7 @@ public class UrnUnwrappingTest { "http://local/base/dtd/docBobPub.dtd" } }; } - private CatalogResolver createResolver() { + private static CatalogResolver createResolver() { return catalogResolver("urnUnwrapping.xml"); } } diff --git a/test/jaxp/javax/xml/jaxp/functional/catalog/ValidateCatalogTest.java b/test/jaxp/javax/xml/jaxp/functional/catalog/ValidateCatalogTest.java index 04676557ea4..c8316c085a2 100644 --- a/test/jaxp/javax/xml/jaxp/functional/catalog/ValidateCatalogTest.java +++ b/test/jaxp/javax/xml/jaxp/functional/catalog/ValidateCatalogTest.java @@ -23,22 +23,23 @@ package catalog; +import org.junit.jupiter.api.Test; + +import javax.xml.catalog.CatalogException; + import static catalog.CatalogTestUtils.CATALOG_SYSTEM; import static catalog.CatalogTestUtils.CATALOG_URI; import static catalog.CatalogTestUtils.catalogResolver; import static catalog.CatalogTestUtils.catalogUriResolver; import static catalog.ResolutionChecker.checkSysIdResolution; import static catalog.ResolutionChecker.checkUriResolution; - -import javax.xml.catalog.CatalogException; - -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @bug 8077931 * @library /javax/xml/jaxp/libs - * @run testng/othervm catalog.ValidateCatalogTest + * @run junit/othervm catalog.ValidateCatalogTest * @summary A legal catalog file must be well-formed XML, the root element * must be catalog, and the naming space of the root element must be * urn:oasis:names:tc:entity:xmlns:xml:catalog. @@ -52,36 +53,36 @@ public class ValidateCatalogTest { * EntityResolver tries to load catalog with wrong root, * it should throw CatalogException. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void validateWrongRootCatalogOnEntityResolver() { - catalogResolver(CATALOG_WRONGROOT); + assertThrows(CatalogException.class, () -> catalogResolver(CATALOG_WRONGROOT)); } /* * URIResolver tries to load catalog with wrong root, * it should throw CatalogException. */ - @Test(expectedExceptions = CatalogException.class) + @Test public void validateWrongRootCatalogOnUriResolver() { - catalogUriResolver(CATALOG_WRONGROOT); + assertThrows(CatalogException.class, () -> catalogUriResolver(CATALOG_WRONGROOT)); } /* * EntityResolver tries to load malformed catalog, * it should throw RuntimeException. */ - @Test(expectedExceptions = RuntimeException.class) + @Test public void validateMalformedCatalogOnEntityResolver() { - catalogResolver(CATALOG_MALFORMED); + assertThrows(RuntimeException.class, () -> catalogResolver(CATALOG_MALFORMED)); } /* * UriResolver tries to load malformed catalog, * it should throw RuntimeException. */ - @Test(expectedExceptions = RuntimeException.class) + @Test public void validateMalformedCatalogOnUriResolver() { - catalogUriResolver(CATALOG_MALFORMED); + assertThrows(RuntimeException.class, () -> catalogUriResolver(CATALOG_MALFORMED)); } /* diff --git a/test/jaxp/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java b/test/jaxp/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java index 6253e26d6e4..a6ab94b9d7e 100644 --- a/test/jaxp/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java +++ b/test/jaxp/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java @@ -30,12 +30,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map; -import java.util.stream.Collectors; import java.util.stream.Stream; import javax.xml.catalog.CatalogFeatures; import javax.xml.catalog.CatalogManager; import javax.xml.catalog.CatalogResolver; -import jaxp.library.JAXPTestUtilities; /* * Utilities for testing XML Catalog API. @@ -69,6 +67,9 @@ final class CatalogTestUtils { private static final String JAXP_PROPS = "jaxp.properties"; private static final String JAXP_PROPS_BAK = JAXP_PROPS + ".bak"; + private static final Path CATALOG_DIR = + Path.of(System.getProperty("test.src")).resolve("catalogFiles").normalize().toAbsolutePath(); + private CatalogTestUtils() { } /* ********** create resolver ********** */ @@ -109,19 +110,12 @@ final class CatalogTestUtils { // Gets the paths of the specified catalogs. private static URI[] getCatalogPaths(String... catalogNames) { - return catalogNames == null - ? null - : Stream.of(catalogNames).map( - catalogName -> getCatalogPath(catalogName)).collect( - Collectors.toList()).toArray(new URI[0]); + return Stream.of(catalogNames).map(CatalogTestUtils::getCatalogPath).toList().toArray(new URI[0]); } // Gets the paths of the specified catalogs. static URI getCatalogPath(String catalogName) { - return catalogName == null - ? null - : Paths.get(JAXPTestUtilities.getPathByClassName(CatalogTestUtils.class, "catalogFiles") - + catalogName).toUri(); + return CATALOG_DIR.resolve(catalogName).toUri(); } /* ********** jaxp.properties ********** */ diff --git a/test/jaxp/javax/xml/jaxp/libs/catalog/ResolutionChecker.java b/test/jaxp/javax/xml/jaxp/libs/catalog/ResolutionChecker.java index 81013a5a7bd..1e06a353c24 100644 --- a/test/jaxp/javax/xml/jaxp/libs/catalog/ResolutionChecker.java +++ b/test/jaxp/javax/xml/jaxp/libs/catalog/ResolutionChecker.java @@ -25,12 +25,13 @@ package catalog; import javax.xml.catalog.CatalogResolver; -import org.testng.Assert; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * Utilities for checking catalog resolution. */ -class ResolutionChecker { +final class ResolutionChecker { /* ********** Checks normal resolution ********** */ @@ -38,8 +39,8 @@ class ResolutionChecker { * Checks the resolution result for specified external identifier. */ static void checkExtIdResolution(CatalogResolver resolver, - String publicId, String systemId, String matchedUri) { - Assert.assertEquals( + String publicId, String systemId, String matchedUri) { + assertEquals( resolver.resolveEntity(publicId, getNotSpecified(systemId)).getSystemId(), matchedUri); } @@ -65,8 +66,8 @@ class ResolutionChecker { * with the specified base location. */ static void checkUriResolution(CatalogResolver resolver, - String href, String base, String matchedUri) { - Assert.assertEquals(resolver.resolve(href, base).getSystemId(), + String href, String base, String matchedUri) { + assertEquals(resolver.resolve(href, base).getSystemId(), matchedUri); } @@ -106,9 +107,9 @@ class ResolutionChecker { static void expectExceptionOnExtId( CatalogResolver resolver, String publicId, String systemId, Class expectedExceptionClass) { - expectThrows(expectedExceptionClass, () -> { - resolver.resolveEntity(publicId, getNotSpecified(systemId)); - }); + assertThrows( + expectedExceptionClass, + () -> resolver.resolveEntity(publicId, getNotSpecified(systemId))); } /* @@ -140,9 +141,7 @@ class ResolutionChecker { static void expectExceptionOnUri( CatalogResolver resolver, String href, String base, Class expectedExceptionClass) { - expectThrows(expectedExceptionClass, () -> { - resolver.resolve(href, base); - }); + assertThrows(expectedExceptionClass, () -> resolver.resolve(href, base)); } /* @@ -155,31 +154,6 @@ class ResolutionChecker { expectExceptionOnUri(resolver, href, null, expectedExceptionClass); } - // The TestNG distribution in current JTREG build doesn't support - // method Assert.expectThrows(). - private static T expectThrows(Class throwableClass, - ThrowingRunnable runnable) { - try { - runnable.run(); - } catch (Throwable t) { - if (throwableClass.isInstance(t)) { - return throwableClass.cast(t); - } else { - String mismatchMessage = String.format( - "Expected %s to be thrown, but %s was thrown", - throwableClass.getSimpleName(), - t.getClass().getSimpleName()); - - throw new AssertionError(mismatchMessage, t); - } - } - - String message = String.format( - "Expected %s to be thrown, but nothing was thrown", - throwableClass.getSimpleName()); - throw new AssertionError(message); - } - /* * SystemId can never be null in XML. For publicId tests, if systemId is null, * it will be considered as not-specified instead. A non-existent systemId @@ -191,8 +165,4 @@ class ResolutionChecker { } return systemId; } - - private interface ThrowingRunnable { - void run() throws Throwable; - } } From 375f8216271b370740658c40e826ae47e13a07fb Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 9 Mar 2026 13:54:11 +0000 Subject: [PATCH 120/170] 8379515: draft-ietf-lamps-kyber-certificates is now RFC 9935 Reviewed-by: mullan --- .../share/classes/sun/security/util/KeyChoices.java | 4 ++-- src/java.base/share/conf/security/java.security | 2 +- .../security/provider/pqc/PrivateKeyEncodings.java | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/classes/sun/security/util/KeyChoices.java b/src/java.base/share/classes/sun/security/util/KeyChoices.java index da3c611750e..00c4463d098 100644 --- a/src/java.base/share/classes/sun/security/util/KeyChoices.java +++ b/src/java.base/share/classes/sun/security/util/KeyChoices.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ import java.util.function.BiFunction; * * This class supports reading, writing, and converting between them. *

      - * Current code follows draft-ietf-lamps-kyber-certificates-11 and RFC 9881. + * Current code follows RFC 9935 and RFC 9881. */ public final class KeyChoices { diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index ef4d7285f51..d5d0488a004 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -1704,7 +1704,7 @@ com.sun.security.allowedAIALocations= # # PKCS #8 encoding format for newly created ML-KEM and ML-DSA private keys # -# draft-ietf-lamps-kyber-certificates-11 and RFC 9881 define three possible formats for a private key: +# RFC 9935 and RFC 9881 define three possible formats for a private key: # a seed (64 bytes for ML-KEM, 32 bytes for ML-DSA), an expanded private key, # or a sequence containing both. # diff --git a/test/jdk/sun/security/provider/pqc/PrivateKeyEncodings.java b/test/jdk/sun/security/provider/pqc/PrivateKeyEncodings.java index 25060d0b74e..39183eb9881 100644 --- a/test/jdk/sun/security/provider/pqc/PrivateKeyEncodings.java +++ b/test/jdk/sun/security/provider/pqc/PrivateKeyEncodings.java @@ -26,7 +26,7 @@ * @bug 8347938 * @library /test/lib * @summary ensure ML-KEM and ML-DSA encodings consistent with - * draft-ietf-lamps-kyber-certificates-11 and RFC 9881 + * RFC 9935 and RFC 9881 * @modules java.base/com.sun.crypto.provider * java.base/sun.security.pkcs * java.base/sun.security.provider @@ -62,17 +62,17 @@ import java.util.stream.Collectors; public class PrivateKeyEncodings { public static void main(String[] args) throws Exception { - // Example keys and certificates draft-ietf-lamps-kyber-certificates-11, Appendix B - // (https://datatracker.ietf.org/doc/html/draft-ietf-lamps-kyber-certificates-11#autoid-17) - // and RFC 9881, Appendix C.3 - // (https://datatracker.ietf.org/doc/html/rfc9881#name-example-certificates) + // Example keys and certificates in RFC 9935, Appendix C + // (https://datatracker.ietf.org/doc/html/rfc9935#name-examples) + // and RFC 9881, Appendix C + // (https://datatracker.ietf.org/doc/html/rfc9881#name-examples) // // These data can be retrieved from the following GitHub releases: // https://github.com/lamps-wg/kyber-certificates/releases/tag/draft-ietf-lamps-kyber-certificates-11 // https://github.com/lamps-wg/dilithium-certificates/releases/tag/draft-ietf-lamps-dilithium-certificates-13 // // Although the release tags include "draft", these values are the - // same as those in the final RFC 9881. + // same as those in the final RFCs. try (var kemReader = RepositoryFileReader.of(RepositoryFileReader.KYBER_CERTIFICATES.class, "kyber-certificates-draft-ietf-lamps-kyber-certificates-11/"); var dsaReader = RepositoryFileReader.of(RepositoryFileReader.DILITHIUM_CERTIFICATES.class, From b9e7ca9cff2b0d2fbffd64e1fe44b049bd0b8935 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 9 Mar 2026 14:12:03 +0000 Subject: [PATCH 121/170] 8375130: [BACKOUT] Scalability issue when submitting virtual threads with almost empty tasks Reviewed-by: alanb --- .../java/util/concurrent/ForkJoinPool.java | 629 +++++++++--------- .../util/concurrent/forkjoin/Starvation.java | 20 +- 2 files changed, 326 insertions(+), 323 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index f289186e0ad..e83a92e5e6f 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -560,70 +560,89 @@ public class ForkJoinPool extends AbstractExecutorService * access (which is usually needed anyway). * * Signalling. Signals (in signalWork) cause new or reactivated - * workers to scan for tasks. SignalWork is invoked in two cases: - * (1) When a task is pushed onto an empty queue, and (2) When a - * worker takes a top-level task from a queue that has additional - * tasks. Together, these suffice in O(log(#threads)) steps to - * fully activate with at least enough workers, and ideally no - * more than required. This ideal is unobtainable: Callers do not - * know whether another worker will finish its current task and - * poll for others without need of a signal (which is otherwise an - * advantage of work-stealing vs other schemes), and also must - * conservatively estimate the triggering conditions of emptiness - * or non-emptiness; all of which usually cause more activations - * than necessary (see below). (Method signalWork is also used as - * failsafe in case of Thread failures in deregisterWorker, to - * activate or create a new worker to replace them). + * workers to scan for tasks. Method signalWork and its callers + * try to approximate the unattainable goal of having the right + * number of workers activated for the tasks at hand, but must err + * on the side of too many workers vs too few to avoid stalls: * - * Top-Level scheduling - * ==================== + * * If computations are purely tree structured, it suffices for + * every worker to activate another when it pushes a task into + * an empty queue, resulting in O(log(#threads)) steps to full + * activation. Emptiness must be conservatively approximated, + * which may result in unnecessary signals. Also, to reduce + * resource usages in some cases, at the expense of slower + * startup in others, activation of an idle thread is preferred + * over creating a new one, here and elsewhere. + * + * * At the other extreme, if "flat" tasks (those that do not in + * turn generate others) come in serially from only a single + * producer, each worker taking a task from a queue should + * propagate a signal if there are more tasks in that + * queue. This is equivalent to, but generally faster than, + * arranging the stealer take multiple tasks, re-pushing one or + * more on its own queue, and signalling (because its queue is + * empty), also resulting in logarithmic full activation + * time. If tasks do not not engage in unbounded loops based on + * the actions of other workers with unknown dependencies loop, + * this form of proagation can be limited to one signal per + * activation (phase change). We distinguish the cases by + * further signalling only if the task is an InterruptibleTask + * (see below), which are the only supported forms of task that + * may do so. + * + * * Because we don't know about usage patterns (or most commonly, + * mixtures), we use both approaches, which present even more + * opportunities to over-signal. (Failure to distinguish these + * cases in terms of submission methods was arguably an early + * design mistake.) Note that in either of these contexts, + * signals may be (and often are) unnecessary because active + * workers continue scanning after running tasks without the + * need to be signalled (which is one reason work stealing is + * often faster than alternatives), so additional workers + * aren't needed. + * + * * For rapidly branching tasks that require full pool resources, + * oversignalling is OK, because signalWork will soon have no + * more workers to create or reactivate. But for others (mainly + * externally submitted tasks), overprovisioning may cause very + * noticeable slowdowns due to contention and resource + * wastage. We reduce impact by deactivating workers when + * queues don't have accessible tasks, but reactivating and + * rescanning if other tasks remain. + * + * * Despite these, signal contention and overhead effects still + * occur during ramp-up and ramp-down of small computations. * * Scanning. Method runWorker performs top-level scanning for (and * execution of) tasks by polling a pseudo-random permutation of * the array (by starting at a given index, and using a constant * cyclically exhaustive stride.) It uses the same basic polling * method as WorkQueue.poll(), but restarts with a different - * permutation on each rescan. The pseudorandom generator need - * not have high-quality statistical properties in the long + * permutation on each invocation. The pseudorandom generator + * need not have high-quality statistical properties in the long * term. We use Marsaglia XorShifts, seeded with the Weyl sequence - * from ThreadLocalRandom probes, which are cheap and suffice. + * from ThreadLocalRandom probes, which are cheap and + * suffice. Each queue's polling attempts to avoid becoming stuck + * when other scanners/pollers stall. Scans do not otherwise + * explicitly take into account core affinities, loads, cache + * localities, etc, However, they do exploit temporal locality + * (which usually approximates these) by preferring to re-poll + * from the same queue after a successful poll before trying + * others, which also reduces bookkeeping, cache traffic, and + * scanning overhead. But it also reduces fairness, which is + * partially counteracted by giving up on detected interference + * (which also reduces contention when too many workers try to + * take small tasks from the same queue). * * Deactivation. When no tasks are found by a worker in runWorker, - * it invokes deactivate, that first deactivates (to an IDLE - * phase). Avoiding missed signals during deactivation requires a - * (conservative) rescan, reactivating if there may be tasks to - * poll. Because idle workers are often not yet blocked (parked), - * we use a WorkQueue field to advertise that a waiter actually - * needs unparking upon signal. - * - * When tasks are constructed as (recursive) DAGs, top-level - * scanning is usually infrequent, and doesn't encounter most - * of the following problems addressed by runWorker and awaitWork: - * - * Locality. Polls are organized into "runs", continuing until - * empty or contended, while also minimizing interference by - * postponing bookeeping to ends of runs. This may reduce - * fairness. - * - * Contention. When many workers try to poll few queues, they - * often collide, generating CAS failures and disrupting locality - * of workers already running their tasks. This also leads to - * stalls when tasks cannot be taken because other workers have - * not finished poll operations, which is detected by reading - * ahead in queue arrays. In both cases, workers restart scans in a - * way that approximates randomized backoff. - * - * Oversignalling. When many short top-level tasks are present in - * a small number of queues, the above signalling strategy may - * activate many more workers than needed, worsening locality and - * contention problems, while also generating more global - * contention (field ctl is CASed on every activation and - * deactivation). We filter out (both in runWorker and - * signalWork) attempted signals that are surely not needed - * because the signalled tasks are already taken. - * - * Shutdown and Quiescence - * ======================= + * it tries to deactivate()), giving up (and rescanning) on "ctl" + * contention. To avoid missed signals during deactivation, the + * method rescans and reactivates if there may have been a missed + * signal during deactivation. To reduce false-alarm reactivations + * while doing so, we scan multiple times (analogously to method + * quiescent()) before trying to reactivate. Because idle workers + * are often not yet blocked (parked), we use a WorkQueue field to + * advertise that a waiter actually needs unparking upon signal. * * Quiescence. Workers scan looking for work, giving up when they * don't find any, without being sure that none are available. @@ -873,7 +892,9 @@ public class ForkJoinPool extends AbstractExecutorService * shutdown, runners are interrupted so they can cancel. Since * external joining callers never run these tasks, they must await * cancellation by others, which can occur along several different - * paths. + * paths. The inability to rely on caller-runs may also require + * extra signalling (resulting in scanning and contention) so is + * done only conditionally in methods push and runworker. * * Across these APIs, rules for reporting exceptions for tasks * with results accessed via join() differ from those via get(), @@ -940,13 +961,9 @@ public class ForkJoinPool extends AbstractExecutorService * less-contended applications. To help arrange this, some * non-reference fields are declared as "long" even when ints or * shorts would suffice. For class WorkQueue, an - * embedded @Contended isolates the very busy top index, along - * with status and bookkeeping fields written (mostly) by owners, - * that otherwise interfere with reading array and base - * fields. There are other variables commonly contributing to - * false-sharing-related performance issues (including fields of - * class Thread), but we can't do much about this except try to - * minimize access. + * embedded @Contended region segregates fields most heavily + * updated by owners from those most commonly read by stealers or + * other management. * * Initial sizing and resizing of WorkQueue arrays is an even more * delicate tradeoff because the best strategy systematically @@ -955,11 +972,13 @@ public class ForkJoinPool extends AbstractExecutorService * direct false-sharing and indirect cases due to GC bookkeeping * (cardmarks etc), and reduce the number of resizes, which are * not especially fast because they require atomic transfers. - * Currently, arrays are initialized to be just large enough to - * avoid resizing in most tree-structured tasks, but grow rapidly - * until large. (Maintenance note: any changes in fields, queues, - * or their uses, or JVM layout policies, must be accompanied by - * re-evaluation of these placement and sizing decisions.) + * Currently, arrays for workers are initialized to be just large + * enough to avoid resizing in most tree-structured tasks, but + * larger for external queues where both false-sharing problems + * and the need for resizing are more common. (Maintenance note: + * any changes in fields, queues, or their uses, or JVM layout + * policies, must be accompanied by re-evaluation of these + * placement and sizing decisions.) * * Style notes * =========== @@ -1042,11 +1061,17 @@ public class ForkJoinPool extends AbstractExecutorService static final int DEFAULT_COMMON_MAX_SPARES = 256; /** - * Initial capacity of work-stealing queue array. + * Initial capacity of work-stealing queue array for workers. * Must be a power of two, at least 2. See above. */ static final int INITIAL_QUEUE_CAPACITY = 1 << 6; + /** + * Initial capacity of work-stealing queue array for external queues. + * Must be a power of two, at least 2. See above. + */ + static final int INITIAL_EXTERNAL_QUEUE_CAPACITY = 1 << 9; + // conversions among short, int, long static final int SMASK = 0xffff; // (unsigned) short bits static final long LMASK = 0xffffffffL; // lower 32 bits of long @@ -1186,11 +1211,11 @@ public class ForkJoinPool extends AbstractExecutorService @jdk.internal.vm.annotation.Contended("w") int stackPred; // pool stack (ctl) predecessor link @jdk.internal.vm.annotation.Contended("w") - volatile int parking; // nonzero if parked in awaitWork - @jdk.internal.vm.annotation.Contended("w") volatile int source; // source queue id (or DROPPED) @jdk.internal.vm.annotation.Contended("w") int nsteals; // number of steals from other queues + @jdk.internal.vm.annotation.Contended("w") + volatile int parking; // nonzero if parked in awaitWork // Support for atomic operations private static final Unsafe U; @@ -1223,11 +1248,11 @@ public class ForkJoinPool extends AbstractExecutorService */ WorkQueue(ForkJoinWorkerThread owner, int id, int cfg, boolean clearThreadLocals) { + array = new ForkJoinTask[owner == null ? + INITIAL_EXTERNAL_QUEUE_CAPACITY : + INITIAL_QUEUE_CAPACITY]; + this.owner = owner; this.config = (clearThreadLocals) ? cfg | CLEAR_TLS : cfg; - if ((this.owner = owner) == null) { - array = new ForkJoinTask[INITIAL_QUEUE_CAPACITY]; - phase = id | IDLE; - } } /** @@ -1254,27 +1279,27 @@ public class ForkJoinPool extends AbstractExecutorService * @throws RejectedExecutionException if array could not be resized */ final void push(ForkJoinTask task, ForkJoinPool pool, boolean internal) { - int s = top, b = base, m, cap, room; ForkJoinTask[] a, na; - if ((a = array) != null && (cap = a.length) > 0) { // else disabled - int k = (m = cap - 1) & s; - if ((room = m - (s - b)) >= 0) { + int s = top, b = base, m, cap, room; ForkJoinTask[] a; + if ((a = array) != null && (cap = a.length) > 0 && // else disabled + task != null) { + int pk = task.noUserHelp() + 1; // prev slot offset + if ((room = (m = cap - 1) - (s - b)) >= 0) { top = s + 1; - long pos = slotOffset(k); + long pos = slotOffset(m & s); if (!internal) U.putReference(a, pos, task); // inside lock else U.getAndSetReference(a, pos, task); // fully fenced - if (room == 0 && (na = growArray(a, cap, s)) != null) - k = ((a = na).length - 1) & s; // resize + if (room == 0) // resize + growArray(a, cap, s); } if (!internal) unlockPhase(); if (room < 0) throw new RejectedExecutionException("Queue capacity exceeded"); - if (pool != null && - (room == 0 || - U.getReferenceAcquire(a, slotOffset(m & (s - 1))) == null)) - pool.signalWork(a, k); // may have appeared empty + if ((room == 0 || U.getReferenceAcquire(a, slotOffset(m & (s - pk))) == null) && + pool != null) + pool.signalWork(); // may have appeared empty } } @@ -1283,12 +1308,11 @@ public class ForkJoinPool extends AbstractExecutorService * @param a old array * @param cap old array capacity * @param s current top - * @return new array, or null on failure */ - private ForkJoinTask[] growArray(ForkJoinTask[] a, int cap, int s) { - int newCap = (cap >= 1 << 16) ? cap << 1 : cap << 2; - ForkJoinTask[] newArray = null; + private void growArray(ForkJoinTask[] a, int cap, int s) { + int newCap = cap << 1; if (a != null && a.length == cap && cap > 0 && newCap > 0) { + ForkJoinTask[] newArray = null; try { newArray = new ForkJoinTask[newCap]; } catch (OutOfMemoryError ex) { @@ -1305,45 +1329,34 @@ public class ForkJoinPool extends AbstractExecutorService updateArray(newArray); // fully fenced } } - return newArray; } /** - * Takes next task, if one exists, in lifo order. + * Takes next task, if one exists, in order specified by mode, + * so acts as either local-pop or local-poll. Called only by owner. + * @param fifo nonzero if FIFO mode */ - private ForkJoinTask localPop() { + private ForkJoinTask nextLocalTask(int fifo) { ForkJoinTask t = null; - int s = top - 1, cap; long k; ForkJoinTask[] a; - if ((a = array) != null && (cap = a.length) > 0 && - U.getReference(a, k = slotOffset((cap - 1) & s)) != null && - (t = (ForkJoinTask)U.getAndSetReference(a, k, null)) != null) - updateTop(s); - return t; - } - - /** - * Takes next task, if one exists, in fifo order. - */ - private ForkJoinTask localPoll() { - ForkJoinTask t = null; - int p = top, cap; ForkJoinTask[] a; - if ((a = array) != null && (cap = a.length) > 0) { - for (int b = base; p - b > 0; ) { - int nb = b + 1; - long k = slotOffset((cap - 1) & b); - if (U.getReference(a, k) == null) { - if (nb == p) - break; // else base is lagging - while (b == (b = U.getIntAcquire(this, BASE))) - Thread.onSpinWait(); // spin to reduce memory traffic + ForkJoinTask[] a = array; + int b = base, p = top, cap; + if (p - b > 0 && a != null && (cap = a.length) > 0) { + for (int m = cap - 1, s, nb;;) { + if (fifo == 0 || (nb = b + 1) == p) { + if ((t = (ForkJoinTask)U.getAndSetReference( + a, slotOffset(m & (s = p - 1)), null)) != null) + updateTop(s); // else lost race for only task + break; } - else if ((t = (ForkJoinTask) - U.getAndSetReference(a, k, null)) != null) { + if ((t = (ForkJoinTask)U.getAndSetReference( + a, slotOffset(m & b), null)) != null) { updateBase(nb); break; } - else - b = base; + while (b == (b = U.getIntAcquire(this, BASE))) + Thread.onSpinWait(); // spin to reduce memory traffic + if (p - b <= 0) + break; } } return t; @@ -1351,9 +1364,10 @@ public class ForkJoinPool extends AbstractExecutorService /** * Takes next task, if one exists, using configured mode. + * (Always internal, never called for Common pool.) */ final ForkJoinTask nextLocalTask() { - return (config & FIFO) == 0 ? localPop() : localPoll(); + return nextLocalTask(config & FIFO); } /** @@ -1429,12 +1443,12 @@ public class ForkJoinPool extends AbstractExecutorService // specialized execution methods /** - * Runs the given task, as well as remaining local tasks + * Runs the given task, as well as remaining local tasks. */ final void topLevelExec(ForkJoinTask task, int fifo) { while (task != null) { task.doExec(); - task = (fifo != 0) ? localPoll() : localPop(); + task = nextLocalTask(fifo); } } @@ -1564,7 +1578,7 @@ public class ForkJoinPool extends AbstractExecutorService * Cancels all local tasks. Called only by owner. */ final void cancelTasks() { - for (ForkJoinTask t; (t = localPop()) != null; ) { + for (ForkJoinTask t; (t = nextLocalTask(0)) != null; ) { try { t.cancel(false); } catch (Throwable ignore) { @@ -1766,8 +1780,7 @@ public class ForkJoinPool extends AbstractExecutorService * @param w caller's WorkQueue */ final void registerWorker(WorkQueue w) { - if (w != null) { - w.array = new ForkJoinTask[INITIAL_QUEUE_CAPACITY]; + if (w != null && (runState & STOP) == 0L) { ThreadLocalRandom.localInit(); int seed = w.stackPred = ThreadLocalRandom.getProbe(); int phaseSeq = seed & ~((IDLE << 1) - 1); // initial phase tag @@ -1845,18 +1858,17 @@ public class ForkJoinPool extends AbstractExecutorService } if ((tryTerminate(false, false) & STOP) == 0L && phase != 0 && w != null && w.source != DROPPED) { + signalWork(); // possibly replace w.cancelTasks(); // clean queue - signalWork(null, 0); // possibly replace } if (ex != null) ForkJoinTask.rethrow(ex); } /** - * Releases an idle worker, or creates one if not enough exist, - * giving up if array a is nonnull and task at a[k] already taken. + * Releases an idle worker, or creates one if not enough exist. */ - final void signalWork(ForkJoinTask[] a, int k) { + final void signalWork() { int pc = parallelism; for (long c = ctl;;) { WorkQueue[] qs = queues; @@ -1872,15 +1884,13 @@ public class ForkJoinPool extends AbstractExecutorService if (sp == 0) { if ((short)(c >>> TC_SHIFT) >= pc) break; - nc = ((c + TC_UNIT) & TC_MASK) | ac; + nc = ((c + TC_UNIT) & TC_MASK); } else if ((v = w) == null) break; else - nc = (v.stackPred & LMASK) | (c & TC_MASK) | ac; - if (a != null && k < a.length && k >= 0 && a[k] == null) - break; - if (c == (c = ctl) && c == (c = compareAndExchangeCtl(c, nc))) { + nc = (v.stackPred & LMASK) | (c & TC_MASK); + if (c == (c = compareAndExchangeCtl(c, nc | ac))) { if (v == null) createWorker(); else { @@ -1963,196 +1973,178 @@ public class ForkJoinPool extends AbstractExecutorService * @param w caller's WorkQueue (may be null on failed initialization) */ final void runWorker(WorkQueue w) { - if (w != null && w.phase != 0) { // else unregistered - WorkQueue[] qs; - int r = w.stackPred; // seed from registerWorker - int fifo = (int)config & FIFO, rescans = 0, inactive = 0, taken = 0, n; - while ((runState & STOP) == 0L && (qs = queues) != null && - (n = qs.length) > 0) { - int i = r, step = (r >>> 16) | 1; + if (w != null) { + int phase = w.phase, r = w.stackPred; // seed from registerWorker + int fifo = w.config & FIFO, nsteals = 0, src = -1; + for (;;) { + WorkQueue[] qs; r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift - scan: for (int j = n; j != 0; --j, i += step) { - WorkQueue q; int qid; - if ((q = qs[qid = i & (n - 1)]) != null) { - ForkJoinTask[] a; int cap; // poll queue - while ((a = q.array) != null && (cap = a.length) > 0) { - int b, nb, nk; long bp; ForkJoinTask t; + if ((runState & STOP) != 0L || (qs = queues) == null) + break; + int n = qs.length, i = r, step = (r >>> 16) | 1; + boolean rescan = false; + scan: for (int l = n; l > 0; --l, i += step) { // scan queues + int j, cap; WorkQueue q; ForkJoinTask[] a; + if ((q = qs[j = i & (n - 1)]) != null && + (a = q.array) != null && (cap = a.length) > 0) { + for (int m = cap - 1, pb = -1, b = q.base;;) { + ForkJoinTask t; long k; t = (ForkJoinTask)U.getReferenceAcquire( - a, bp = slotOffset((cap - 1) & (b = q.base))); - long np = slotOffset(nk = (nb = b + 1) & (cap - 1)); - if (q.base == b) { // else inconsistent - if (t == null) { - if (q.array == a) { // else resized - if (rescans > 0) // ran or stalled - break scan; - if (U.getReference(a, np) == null && - (rescans >= 0 || - (U.getReferenceAcquire(a, bp) == null && - q.top == q.base))) - break; - rescans = 1; // may be stalled + a, k = slotOffset(m & b)); + if (b != (b = q.base) || t == null || + !U.compareAndSetReference(a, k, t, null)) { + if (a[b & m] == null) { + if (rescan) // end of run + break scan; + if (a[(b + 1) & m] == null && + a[(b + 2) & m] == null) { + break; // probably empty } - } - else if (inactive != 0) { - if ((inactive = tryReactivate(w)) != 0) { - rescans = 1; // can't take yet + if (pb == (pb = b)) { // track progress + rescan = true; // stalled; reorder scan break scan; } } - else if (U.compareAndSetReference(a, bp, t, null)) { - q.base = nb; - Object nt = U.getReferenceAcquire(a, np); - w.source = qid; - rescans = 1; - ++taken; - if (nt != null && // confirm a[nk] - U.getReferenceAcquire(a, np) == nt) - signalWork(a, nk); // propagate - w.topLevelExec(t, fifo); - } + } + else { + boolean propagate; + int nb = q.base = b + 1, prevSrc = src; + w.nsteals = ++nsteals; + w.source = src = j; // volatile + rescan = true; + int nh = t.noUserHelp(); + if (propagate = + (prevSrc != src || nh != 0) && a[nb & m] != null) + signalWork(); + w.topLevelExec(t, fifo); + if ((b = q.base) != nb && !propagate) + break scan; // reduce interference } } } } - if (rescans >= 0) - --rescans; - else if (inactive == 0) { - if ((inactive = deactivate(w, taken)) != 0) - taken = 0; + if (!rescan) { + if (((phase = deactivate(w, phase)) & IDLE) != 0) + break; + src = -1; // re-enable propagation } - else if (awaitWork(w) == 0) - inactive = rescans = 0; - else - break; } } } /** - * Tries to deactivate worker, keeping active on contention + * Deactivates and if necessary awaits signal or termination. * - * @param w the work queue - * @param taken number of stolen tasks since last deactivation - * @return nonzero if inactive + * @param w the worker + * @param phase current phase + * @return current phase, with IDLE set if worker should exit */ - private int deactivate(WorkQueue w, int taken) { - int inactive = 0, phase; - if (w != null && (inactive = (phase = w.phase) & IDLE) == 0) { - long sp = (phase + (IDLE << 1)) & LMASK, pc, c; - w.phase = phase | IDLE; - w.stackPred = (int)(pc = ctl); // set ctl stack link - if (!compareAndSetCtl( // try to enqueue - pc, c = ((pc - RC_UNIT) & UMASK) | sp)) - w.phase = phase; // back out on contention - else { - if (taken != 0) { - w.nsteals += taken; - if ((w.config & CLEAR_TLS) != 0 && - (Thread.currentThread() instanceof ForkJoinWorkerThread f)) - f.resetThreadLocals(); // (instanceof check always true) - } - if (((c & RC_MASK) == 0L && quiescent() > 0) || taken == 0) - inactive = w.phase & IDLE; // check quiescent termination - else { // spin for approx 1 scan cost - int tc = (short)(c >>> TC_SHIFT); - int spins = Math.max((tc << 1) + tc, SPIN_WAITS); - while ((inactive = w.phase & IDLE) != 0 && --spins != 0) - Thread.onSpinWait(); - } - } - } - return inactive; - } + private int deactivate(WorkQueue w, int phase) { + if (w == null) // currently impossible + return IDLE; + int p = phase | IDLE, activePhase = phase + (IDLE << 1); + long pc = ctl, qc = (activePhase & LMASK) | ((pc - RC_UNIT) & UMASK); + int sp = w.stackPred = (int)pc; // set ctl stack link + w.phase = p; + if (!compareAndSetCtl(pc, qc)) // try to enqueue + return w.phase = phase; // back out on possible signal + int ac = (short)(qc >>> RC_SHIFT), n; long e; WorkQueue[] qs; + if (((e = runState) & STOP) != 0L || + ((e & SHUTDOWN) != 0L && ac == 0 && quiescent() > 0) || + (qs = queues) == null || (n = qs.length) <= 0) + return IDLE; // terminating - /** - * Reactivates worker w if it is currently top of ctl stack - * - * @param w the work queue - * @return 0 if now active - */ - private int tryReactivate(WorkQueue w) { - int inactive = 0; - if (w != null) { // always true; hoist checks - int sp = w.stackPred, phase, activePhase; long c; - if ((inactive = (phase = w.phase) & IDLE) != 0 && - (int)(c = ctl) == (activePhase = phase + IDLE) && - compareAndSetCtl(c, (sp & LMASK) | ((c + RC_UNIT) & UMASK))) { - w.phase = activePhase; - inactive = 0; - } + for (int prechecks = Math.min(ac, 2), // reactivation threshold + k = Math.max(n + (n << 1), SPIN_WAITS << 1);;) { + WorkQueue q; int cap; ForkJoinTask[] a; long c; + if (w.phase == activePhase) + return activePhase; + if (--k < 0) + return awaitWork(w, p); // block, drop, or exit + if ((q = qs[k & (n - 1)]) == null) + Thread.onSpinWait(); + else if ((a = q.array) != null && (cap = a.length) > 0 && + a[q.base & (cap - 1)] != null && --prechecks < 0 && + (int)(c = ctl) == activePhase && + compareAndSetCtl(c, (sp & LMASK) | ((c + RC_UNIT) & UMASK))) + return w.phase = activePhase; // reactivate } - return inactive; } /** * Awaits signal or termination. * * @param w the work queue - * @return 0 if now active + * @param p current phase (known to be idle) + * @return current phase, with IDLE set if worker should exit */ - private int awaitWork(WorkQueue w) { - int inactive = 0, phase; - if (w != null) { // always true; hoist checks - long waitTime = (w.source == INVALID_ID) ? 0L : keepAlive; - if ((inactive = (phase = w.phase) & IDLE) != 0) { + private int awaitWork(WorkQueue w, int p) { + if (w != null) { + ForkJoinWorkerThread t; long deadline; + if ((w.config & CLEAR_TLS) != 0 && (t = w.owner) != null) + t.resetThreadLocals(); // clear before reactivate + if ((ctl & RC_MASK) > 0L) + deadline = 0L; + else if ((deadline = + (((w.source != INVALID_ID) ? keepAlive : TIMEOUT_SLOP)) + + System.currentTimeMillis()) == 0L) + deadline = 1L; // avoid zero + int activePhase = p + IDLE; + if ((p = w.phase) != activePhase && (runState & STOP) == 0L) { LockSupport.setCurrentBlocker(this); - int activePhase = phase + IDLE; - for (long deadline = 0L;;) { - Thread.interrupted(); // clear status + w.parking = 1; // enable unpark + while ((p = w.phase) != activePhase) { + boolean trimmable = false; int trim; + Thread.interrupted(); // clear status if ((runState & STOP) != 0L) break; - boolean trimmable = false; // use timed wait if trimmable - long d = 0L, c; - if (((c = ctl) & RC_MASK) == 0L && (int)c == activePhase) { - long now = System.currentTimeMillis(); - if (deadline == 0L) - deadline = waitTime + now; - if (deadline - now <= TIMEOUT_SLOP) { - if (tryTrim(w, c, activePhase)) - break; - continue; // lost race to trim - } - d = deadline; - trimmable = true; + if (deadline != 0L) { + if ((trim = tryTrim(w, p, deadline)) > 0) + break; + else if (trim < 0) + deadline = 0L; + else + trimmable = true; } - w.parking = 1; // enable unpark and recheck - if ((inactive = w.phase & IDLE) != 0) - U.park(trimmable, d); - w.parking = 0; // close unpark window - if (inactive == 0 || (inactive = w.phase & IDLE) == 0) - break; + U.park(trimmable, deadline); } + w.parking = 0; LockSupport.setCurrentBlocker(null); } } - return inactive; + return p; } /** * Tries to remove and deregister worker after timeout, and release - * another to do the same unless new tasks are found. + * another to do the same. + * @return > 0: trimmed, < 0 : not trimmable, else 0 */ - private boolean tryTrim(WorkQueue w, long c, int activePhase) { - if (w != null) { - int vp, i; WorkQueue[] vs; WorkQueue v; - long nc = ((w.stackPred & LMASK) | - ((RC_MASK & c) | (TC_MASK & (c - TC_UNIT)))); - if (compareAndSetCtl(c, nc)) { - w.source = DROPPED; - w.phase = activePhase; - if ((vp = (int)nc) != 0 && (vs = queues) != null && - vs.length > (i = vp & SMASK) && (v = vs[i]) != null && - compareAndSetCtl( // try to wake up next waiter - nc, ((v.stackPred & LMASK) | - ((UMASK & (nc + RC_UNIT)) | (nc & TC_MASK))))) { - v.source = INVALID_ID; // enable cascaded timeouts - v.phase = vp; - U.unpark(v.owner); - } - return true; + private int tryTrim(WorkQueue w, int phase, long deadline) { + long c, nc; int stat, activePhase, vp, i; WorkQueue[] vs; WorkQueue v; + if ((activePhase = phase + IDLE) != (int)(c = ctl) || w == null) + stat = -1; // no longer ctl top + else if (deadline - System.currentTimeMillis() >= TIMEOUT_SLOP) + stat = 0; // spurious wakeup + else if (!compareAndSetCtl( + c, nc = ((w.stackPred & LMASK) | (RC_MASK & c) | + (TC_MASK & (c - TC_UNIT))))) + stat = -1; // lost race to signaller + else { + stat = 1; + w.source = DROPPED; + w.phase = activePhase; + if ((vp = (int)nc) != 0 && (vs = queues) != null && + vs.length > (i = vp & SMASK) && (v = vs[i]) != null && + compareAndSetCtl( // try to wake up next waiter + nc, ((UMASK & (nc + RC_UNIT)) | + (nc & TC_MASK) | (v.stackPred & LMASK)))) { + v.source = INVALID_ID; // enable cascaded timeouts + v.phase = vp; + U.unpark(v.owner); } } - return false; + return stat; } /** @@ -2569,35 +2561,52 @@ public class ForkJoinPool extends AbstractExecutorService /** * Finds and locks a WorkQueue for an external submitter, or - * throws RejectedExecutionException if shutdown + * throws RejectedExecutionException if shutdown or terminating. + * @param r current ThreadLocalRandom.getProbe() value * @param rejectOnShutdown true if RejectedExecutionException - * should be thrown when shutdown + * should be thrown when shutdown (else only if terminating) */ - final WorkQueue externalSubmissionQueue(boolean rejectOnShutdown) { - int r; - if ((r = ThreadLocalRandom.getProbe()) == 0) { - ThreadLocalRandom.localInit(); // initialize caller's probe + private WorkQueue submissionQueue(int r, boolean rejectOnShutdown) { + int reuse; // nonzero if prefer create + if ((reuse = r) == 0) { + ThreadLocalRandom.localInit(); // initialize caller's probe r = ThreadLocalRandom.getProbe(); } - for (;;) { - WorkQueue q; WorkQueue[] qs; int n, id, i; - if ((qs = queues) == null || (n = qs.length) <= 0) + for (int probes = 0; ; ++probes) { + int n, i, id; WorkQueue[] qs; WorkQueue q; + if ((qs = queues) == null) + break; + if ((n = qs.length) <= 0) break; if ((q = qs[i = (id = r & EXTERNAL_ID_MASK) & (n - 1)]) == null) { - WorkQueue newq = new WorkQueue(null, id, 0, false); - lockRunState(); - if (qs[i] == null && queues == qs) - q = qs[i] = newq; // else lost race to install + WorkQueue w = new WorkQueue(null, id, 0, false); + w.phase = id; + boolean reject = ((lockRunState() & SHUTDOWN) != 0 && + rejectOnShutdown); + if (!reject && queues == qs && qs[i] == null) + q = qs[i] = w; // else lost race to install unlockRunState(); - } - if (q != null && q.tryLockPhase()) { - if (rejectOnShutdown && (runState & SHUTDOWN) != 0L) { - q.unlockPhase(); // check while q lock held + if (q != null) + return q; + if (reject) break; - } - return q; + reuse = 0; } - r = ThreadLocalRandom.advanceProbe(r); // move + if (reuse == 0 || !q.tryLockPhase()) { // move index + if (reuse == 0) { + if (probes >= n >> 1) + reuse = r; // stop prefering free slot + } + else if (q != null) + reuse = 0; // probe on collision + r = ThreadLocalRandom.advanceProbe(r); + } + else if (rejectOnShutdown && (runState & SHUTDOWN) != 0L) { + q.unlockPhase(); // check while q lock held + break; + } + else + return q; } throw new RejectedExecutionException(); } @@ -2611,12 +2620,24 @@ public class ForkJoinPool extends AbstractExecutorService } else { // find and lock queue internal = false; - q = externalSubmissionQueue(true); + q = submissionQueue(ThreadLocalRandom.getProbe(), true); } q.push(task, signalIfEmpty ? this : null, internal); return task; } + /** + * Returns queue for an external submission, bypassing call to + * submissionQueue if already established and unlocked. + */ + final WorkQueue externalSubmissionQueue(boolean rejectOnShutdown) { + WorkQueue[] qs; WorkQueue q; int n; + int r = ThreadLocalRandom.getProbe(); + return (((qs = queues) != null && (n = qs.length) > 0 && + (q = qs[r & EXTERNAL_ID_MASK & (n - 1)]) != null && r != 0 && + q.tryLockPhase()) ? q : submissionQueue(r, rejectOnShutdown)); + } + /** * Returns queue for an external thread, if one exists that has * possibly ever submitted to the given pool (nonzero probe), or @@ -3295,7 +3316,7 @@ public class ForkJoinPool extends AbstractExecutorService if ((config & PRESET_SIZE) != 0) throw new UnsupportedOperationException("Cannot override System property"); if ((prevSize = getAndSetParallelism(size)) < size) - signalWork(null, 0); // trigger worker activation + signalWork(); // trigger worker activation return prevSize; } diff --git a/test/jdk/java/util/concurrent/forkjoin/Starvation.java b/test/jdk/java/util/concurrent/forkjoin/Starvation.java index f3336a3c7e9..3db83688d45 100644 --- a/test/jdk/java/util/concurrent/forkjoin/Starvation.java +++ b/test/jdk/java/util/concurrent/forkjoin/Starvation.java @@ -28,7 +28,6 @@ */ import java.util.concurrent.Callable; import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinTask; import java.util.concurrent.atomic.AtomicInteger; public class Starvation { @@ -43,7 +42,7 @@ public class Starvation { while (count.get() == c) Thread.onSpinWait(); return null; }}; - static void testSubmitExternalCallable() throws Exception { + public static void main(String[] args) throws Exception { try (var pool = new ForkJoinPool(2)) { for (int i = 0; i < 100_000; i++) { var future1 = pool.submit(new AwaitCount(i)); @@ -54,21 +53,4 @@ public class Starvation { } } } - - static void testSubmitAdaptedCallable() throws Exception { - try (var pool = new ForkJoinPool(2)) { - for (int i = 0; i < 100_000; i++) { - var future1 = pool.submit(new AwaitCount(i)); - var future2 = pool.submit(ForkJoinTask.adapt(noop)); - future2.get(); - count.set(i + 1); - future1.get(); - } - } - } - - public static void main(String[] args) throws Exception { - testSubmitExternalCallable(); - testSubmitAdaptedCallable(); - } } From a6c5216e5fcd947b40bb674d3659480f43ef6322 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 9 Mar 2026 14:45:27 +0000 Subject: [PATCH 122/170] 8379233: [REDO] Remove some unused code in generateOopMap.cpp Reviewed-by: matsaave, dholmes --- src/hotspot/share/interpreter/oopMapCache.cpp | 26 +-------------- src/hotspot/share/oops/generateOopMap.cpp | 23 ++----------- src/hotspot/share/oops/generateOopMap.hpp | 33 +++---------------- 3 files changed, 8 insertions(+), 74 deletions(-) diff --git a/src/hotspot/share/interpreter/oopMapCache.cpp b/src/hotspot/share/interpreter/oopMapCache.cpp index 29d6825d3e5..d7c02296f33 100644 --- a/src/hotspot/share/interpreter/oopMapCache.cpp +++ b/src/hotspot/share/interpreter/oopMapCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,14 +78,10 @@ class OopMapForCacheEntry: public GenerateOopMap { int _stack_top; virtual bool report_results() const { return false; } - virtual bool possible_gc_point (BytecodeStream *bcs); - virtual void fill_stackmap_prolog (int nof_gc_points); - virtual void fill_stackmap_epilog (); virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top); - virtual void fill_init_vars (GrowableArray *init_vars); public: OopMapForCacheEntry(const methodHandle& method, int bci, OopMapCacheEntry *entry); @@ -120,26 +116,6 @@ bool OopMapForCacheEntry::compute_map(Thread* current) { } -bool OopMapForCacheEntry::possible_gc_point(BytecodeStream *bcs) { - return false; // We are not reporting any result. We call result_for_basicblock directly -} - - -void OopMapForCacheEntry::fill_stackmap_prolog(int nof_gc_points) { - // Do nothing -} - - -void OopMapForCacheEntry::fill_stackmap_epilog() { - // Do nothing -} - - -void OopMapForCacheEntry::fill_init_vars(GrowableArray *init_vars) { - // Do nothing -} - - void OopMapForCacheEntry::fill_stackmap_for_opcodes(BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, diff --git a/src/hotspot/share/oops/generateOopMap.cpp b/src/hotspot/share/oops/generateOopMap.cpp index 97d8bf3d526..5e12c57676d 100644 --- a/src/hotspot/share/oops/generateOopMap.cpp +++ b/src/hotspot/share/oops/generateOopMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -391,7 +391,6 @@ void CellTypeState::print(outputStream *os) { // void GenerateOopMap::initialize_bb() { - _gc_points = 0; _bb_count = 0; _bb_hdr_bits.reinitialize(method()->code_size()); } @@ -409,7 +408,7 @@ void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) { } -void GenerateOopMap::mark_bbheaders_and_count_gc_points() { +void GenerateOopMap::mark_bbheaders() { initialize_bb(); bool fellThrough = false; // False to get first BB marked. @@ -445,9 +444,6 @@ void GenerateOopMap::mark_bbheaders_and_count_gc_points() { default: break; } - - if (possible_gc_point(&bcs)) - _gc_points++; } } @@ -2119,8 +2115,6 @@ bool GenerateOopMap::compute_map(Thread* current) { // if no code - do nothing // compiler needs info if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) { - fill_stackmap_prolog(0); - fill_stackmap_epilog(); return true; } // Step 1: Compute all jump targets and their return value @@ -2129,7 +2123,7 @@ bool GenerateOopMap::compute_map(Thread* current) { // Step 2: Find all basic blocks and count GC points if (!_got_error) - mark_bbheaders_and_count_gc_points(); + mark_bbheaders(); // Step 3: Calculate stack maps if (!_got_error) @@ -2186,9 +2180,6 @@ void GenerateOopMap::report_result() { // We now want to report the result of the parse _report_result = true; - // Prolog code - fill_stackmap_prolog(_gc_points); - // Mark everything changed, then do one interpretation pass. for (int i = 0; i<_bb_count; i++) { if (_basic_blocks[i].is_reachable()) { @@ -2197,14 +2188,6 @@ void GenerateOopMap::report_result() { } } - // Note: Since we are skipping dead-code when we are reporting results, then - // the no. of encountered gc-points might be fewer than the previously number - // we have counted. (dead-code is a pain - it should be removed before we get here) - fill_stackmap_epilog(); - - // Report initvars - fill_init_vars(_init_vars); - _report_result = false; } diff --git a/src/hotspot/share/oops/generateOopMap.hpp b/src/hotspot/share/oops/generateOopMap.hpp index 0da3779d463..783e295f08a 100644 --- a/src/hotspot/share/oops/generateOopMap.hpp +++ b/src/hotspot/share/oops/generateOopMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -348,17 +348,15 @@ class GenerateOopMap { // Basicblock info BasicBlock * _basic_blocks; // Array of basicblock info - int _gc_points; int _bb_count; ResourceBitMap _bb_hdr_bits; // Basicblocks methods void initialize_bb (); - void mark_bbheaders_and_count_gc_points(); + void mark_bbheaders(); bool is_bb_header (int bci) const { return _bb_hdr_bits.at(bci); } - int gc_points () const { return _gc_points; } int bb_count () const { return _bb_count; } void set_bbmark_bit (int bci); BasicBlock * get_basic_block_at (int bci) const; @@ -450,7 +448,7 @@ class GenerateOopMap { int binsToHold (int no) { return ((no+(BitsPerWord-1))/BitsPerWord); } char *state_vec_to_string (CellTypeState* vec, int len); - // Helper method. Can be used in subclasses to fx. calculate gc_points. If the current instruction + // Helper method. If the current instruction // is a control transfer, then calls the jmpFct all possible destinations. void ret_jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int varNo,int *data); bool jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int *data); @@ -480,14 +478,7 @@ class GenerateOopMap { bool monitor_safe() { return _monitor_safe; } // Specialization methods. Intended use: - // - possible_gc_point must return true for every bci for which the stackmaps must be returned - // - fill_stackmap_prolog is called just before the result is reported. The arguments tells the estimated - // number of gc points // - fill_stackmap_for_opcodes is called once for each bytecode index in order (0...code_length-1) - // - fill_stackmap_epilog is called after all results has been reported. Note: Since the algorithm does not report - // stackmaps for deadcode, fewer gc_points might have been encountered than assumed during the epilog. It is the - // responsibility of the subclass to count the correct number. - // - fill_init_vars are called once with the result of the init_vars computation // // All these methods are used during a call to: compute_map. Note: Non of the return results are valid // after compute_map returns, since all values are allocated as resource objects. @@ -496,14 +487,10 @@ class GenerateOopMap { virtual bool allow_rewrites () const { return false; } virtual bool report_results () const { return true; } virtual bool report_init_vars () const { return true; } - virtual bool possible_gc_point (BytecodeStream *bcs) { ShouldNotReachHere(); return false; } - virtual void fill_stackmap_prolog (int nof_gc_points) { ShouldNotReachHere(); } - virtual void fill_stackmap_epilog () { ShouldNotReachHere(); } virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stackTop) { ShouldNotReachHere(); } - virtual void fill_init_vars (GrowableArray *init_vars) { ShouldNotReachHere();; } }; // @@ -513,19 +500,13 @@ class GenerateOopMap { class ResolveOopMapConflicts: public GenerateOopMap { private: - bool _must_clear_locals; - virtual bool report_results() const { return false; } virtual bool report_init_vars() const { return true; } virtual bool allow_rewrites() const { return true; } - virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } - virtual void fill_stackmap_prolog (int nof_gc_points) {} - virtual void fill_stackmap_epilog () {} virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top) {} - virtual void fill_init_vars (GrowableArray *init_vars) { _must_clear_locals = init_vars->length() > 0; } #ifndef PRODUCT // Statistics @@ -535,10 +516,8 @@ class ResolveOopMapConflicts: public GenerateOopMap { #endif public: - ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { _must_clear_locals = false; }; - + ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { } methodHandle do_potential_rewrite(TRAPS); - bool must_clear_locals() const { return _must_clear_locals; } }; @@ -551,14 +530,10 @@ class GeneratePairingInfo: public GenerateOopMap { virtual bool report_results() const { return false; } virtual bool report_init_vars() const { return false; } virtual bool allow_rewrites() const { return false; } - virtual bool possible_gc_point (BytecodeStream *bcs) { return false; } - virtual void fill_stackmap_prolog (int nof_gc_points) {} - virtual void fill_stackmap_epilog () {} virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs, CellTypeState* vars, CellTypeState* stack, int stack_top) {} - virtual void fill_init_vars (GrowableArray *init_vars) {} public: GeneratePairingInfo(const methodHandle& method) : GenerateOopMap(method) {}; From 947d5b6a0205f1d6d516521693dd29d543dada08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Lund=C3=A9n?= Date: Mon, 9 Mar 2026 15:20:20 +0000 Subject: [PATCH 123/170] 8376104: C2 crashes in PhiNode::Ideal(PhaseGVN*, bool) accessing NULL pointer Co-authored-by: Roman Marchenko Reviewed-by: mhaessig, dfenacci, rcastanedalo --- src/hotspot/share/opto/cfgnode.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index c65bc391792..04061a60bad 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2675,6 +2675,10 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { for( uint i=1; i Date: Mon, 9 Mar 2026 15:20:35 +0000 Subject: [PATCH 124/170] 8379443: Correct build tags in some math tests Reviewed-by: iris --- test/jdk/java/lang/Math/HypotTests.java | 3 ++- test/jdk/java/lang/Math/IeeeRecommendedTests.java | 3 ++- test/jdk/java/lang/Math/IeeeRemainderTests.java | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/lang/Math/HypotTests.java b/test/jdk/java/lang/Math/HypotTests.java index e09799e34a4..eee40ea6469 100644 --- a/test/jdk/java/lang/Math/HypotTests.java +++ b/test/jdk/java/lang/Math/HypotTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @library /test/lib * @build jdk.test.lib.RandomFactory + * @build Tests * @run main HypotTests * @bug 4851638 4939441 8078672 8240632 * @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed) diff --git a/test/jdk/java/lang/Math/IeeeRecommendedTests.java b/test/jdk/java/lang/Math/IeeeRecommendedTests.java index 8570508ff44..3dfb70ab9af 100644 --- a/test/jdk/java/lang/Math/IeeeRecommendedTests.java +++ b/test/jdk/java/lang/Math/IeeeRecommendedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @library /test/lib * @build jdk.test.lib.RandomFactory + * @build Tests * @run main IeeeRecommendedTests * @bug 4860891 4826732 4780454 4939441 4826652 8078672 * @summary Tests for IEEE 754[R] recommended functions and similar methods (use -Dseed=X to set PRNG seed) diff --git a/test/jdk/java/lang/Math/IeeeRemainderTests.java b/test/jdk/java/lang/Math/IeeeRemainderTests.java index 596310d8e42..8716be870c9 100644 --- a/test/jdk/java/lang/Math/IeeeRemainderTests.java +++ b/test/jdk/java/lang/Math/IeeeRemainderTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,8 @@ /* * @test * @bug 8304028 + * @build Tests + * @run main IeeeRemainderTests * @summary Tests for {Math, StrictMath}.IEEEremainder */ From 0d2f7f6216f2cf6b8cd18d8e0d51a1458097784f Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Mon, 9 Mar 2026 15:57:33 +0000 Subject: [PATCH 125/170] 8377995: ZGC: Fix implicit narrowing conversion in zBitField Reviewed-by: stefank, aboldtch --- src/hotspot/share/gc/z/zBitField.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/z/zBitField.hpp b/src/hotspot/share/gc/z/zBitField.hpp index 9bec4e05594..b68f5b92ce1 100644 --- a/src/hotspot/share/gc/z/zBitField.hpp +++ b/src/hotspot/share/gc/z/zBitField.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ public: static ContainerType encode(ValueType value) { assert(((ContainerType)value & (FieldMask << ValueShift)) == (ContainerType)value, "Invalid value"); - return ((ContainerType)value >> ValueShift) << FieldShift; + return checked_cast(((ContainerType)value >> ValueShift) << FieldShift); } }; From 7b0024adbb0678050f8755c543068916fdedf4d8 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 9 Mar 2026 16:03:13 +0000 Subject: [PATCH 126/170] 8378804: Shenandoah: Convert remaining components to Atomic Reviewed-by: wkemper, xpeng --- .../share/gc/shenandoah/shenandoahCollectionSet.cpp | 10 +++++----- .../share/gc/shenandoah/shenandoahCollectionSet.hpp | 5 +++-- .../share/gc/shenandoah/shenandoahController.cpp | 4 ++-- .../share/gc/shenandoah/shenandoahController.hpp | 3 ++- .../gc/shenandoah/shenandoahHeapRegionCounters.cpp | 5 ++--- .../gc/shenandoah/shenandoahHeapRegionCounters.hpp | 3 ++- .../share/gc/shenandoah/shenandoahNumberSeq.cpp | 6 +++--- .../share/gc/shenandoah/shenandoahNumberSeq.hpp | 3 ++- .../share/gc/shenandoah/shenandoahRootProcessor.cpp | 2 +- .../share/gc/shenandoah/shenandoahRootProcessor.hpp | 3 ++- .../share/gc/shenandoah/shenandoahScanRemembered.cpp | 2 +- .../share/gc/shenandoah/shenandoahScanRemembered.hpp | 2 +- .../gc/shenandoah/shenandoahScanRemembered.inline.hpp | 6 +++--- .../share/gc/shenandoah/shenandoahTaskqueue.hpp | 9 +++++---- 14 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp index c1c6b876d90..54ab7801ca9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp @@ -136,7 +136,7 @@ void ShenandoahCollectionSet::clear() { _live = 0; _region_count = 0; - _current_index = 0; + _current_index.store_relaxed(0); _young_bytes_to_evacuate = 0; _young_bytes_to_promote = 0; @@ -154,11 +154,11 @@ ShenandoahHeapRegion* ShenandoahCollectionSet::claim_next() { // before hitting the (potentially contended) atomic index. size_t max = _heap->num_regions(); - size_t old = AtomicAccess::load(&_current_index); + size_t old = _current_index.load_relaxed(); for (size_t index = old; index < max; index++) { if (is_in(index)) { - size_t cur = AtomicAccess::cmpxchg(&_current_index, old, index + 1, memory_order_relaxed); + size_t cur = _current_index.compare_exchange(old, index + 1, memory_order_relaxed); assert(cur >= old, "Always move forward"); if (cur == old) { // Successfully moved the claim index, this is our region. @@ -178,9 +178,9 @@ ShenandoahHeapRegion* ShenandoahCollectionSet::next() { assert(Thread::current()->is_VM_thread(), "Must be VMThread"); size_t max = _heap->num_regions(); - for (size_t index = _current_index; index < max; index++) { + for (size_t index = _current_index.load_relaxed(); index < max; index++) { if (is_in(index)) { - _current_index = index + 1; + _current_index.store_relaxed(index + 1); return _heap->get_region(index); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp index c99271de1fb..87b4597c93f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp @@ -32,6 +32,7 @@ #include "memory/allocation.hpp" #include "memory/reservedSpace.hpp" #include "memory/virtualspace.hpp" +#include "runtime/atomic.hpp" class ShenandoahCollectionSet : public CHeapObj { friend class ShenandoahHeap; @@ -80,7 +81,7 @@ private: size_t _old_available_bytes_collected; shenandoah_padding(0); - volatile size_t _current_index; + Atomic _current_index; shenandoah_padding(1); public: @@ -99,7 +100,7 @@ public: bool is_empty() const { return _region_count == 0; } void clear_current_index() { - _current_index = 0; + _current_index.store_relaxed(0); } inline bool is_in(ShenandoahHeapRegion* r) const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahController.cpp b/src/hotspot/share/gc/shenandoah/shenandoahController.cpp index 220f3df8d4f..50aabad7d42 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahController.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahController.cpp @@ -31,11 +31,11 @@ void ShenandoahController::update_gc_id() { - AtomicAccess::inc(&_gc_id); + _gc_id.add_then_fetch((size_t)1); } size_t ShenandoahController::get_gc_id() { - return AtomicAccess::load(&_gc_id); + return _gc_id.load_relaxed(); } void ShenandoahController::handle_alloc_failure(const ShenandoahAllocRequest& req, bool block) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp index b8ff4df4771..60b41a5fe99 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahController.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahController.hpp @@ -29,6 +29,7 @@ #include "gc/shared/gcCause.hpp" #include "gc/shenandoah/shenandoahAllocRequest.hpp" #include "gc/shenandoah/shenandoahSharedVariables.hpp" +#include "runtime/atomic.hpp" /** * This interface exposes methods necessary for the heap to interact @@ -38,7 +39,7 @@ class ShenandoahController: public ConcurrentGCThread { private: shenandoah_padding(0); // A monotonically increasing GC count. - volatile size_t _gc_id; + Atomic _gc_id; shenandoah_padding(1); protected: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp index aed3faef906..ff1e3368e87 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp @@ -32,7 +32,6 @@ #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" -#include "runtime/atomicAccess.hpp" #include "runtime/perfData.inline.hpp" #include "utilities/defaultStream.hpp" @@ -106,8 +105,8 @@ void ShenandoahHeapRegionCounters::write_snapshot(PerfLongVariable** regions, void ShenandoahHeapRegionCounters::update() { if (ShenandoahRegionSampling) { jlong current = nanos_to_millis(os::javaTimeNanos()); - jlong last = _last_sample_millis; - if (current - last > ShenandoahRegionSamplingRate && AtomicAccess::cmpxchg(&_last_sample_millis, last, current) == last) { + jlong last = _last_sample_millis.load_relaxed(); + if (current - last > ShenandoahRegionSamplingRate && _last_sample_millis.compare_exchange(last, current) == last) { ShenandoahHeap* heap = ShenandoahHeap::heap(); _status->set_value(encode_heap_status(heap)); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp index 508b40e49a8..d50188bf70c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.hpp @@ -28,6 +28,7 @@ #include "logging/logFileStreamOutput.hpp" #include "memory/allocation.hpp" +#include "runtime/atomic.hpp" /** * This provides the following in JVMStat: @@ -88,7 +89,7 @@ private: PerfLongVariable** _regions_data; PerfLongVariable* _timestamp; PerfLongVariable* _status; - volatile jlong _last_sample_millis; + Atomic _last_sample_millis; void write_snapshot(PerfLongVariable** regions, PerfLongVariable* ts, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp index 32c63e9b186..1ddd8e1c032 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp @@ -198,11 +198,11 @@ void BinaryMagnitudeSeq::clear() { for (int c = 0; c < BitsPerSize_t; c++) { _mags[c] = 0; } - _sum = 0; + _sum.store_relaxed(0); } void BinaryMagnitudeSeq::add(size_t val) { - AtomicAccess::add(&_sum, val); + _sum.add_then_fetch(val); int mag = log2i_graceful(val) + 1; @@ -237,7 +237,7 @@ size_t BinaryMagnitudeSeq::num() const { } size_t BinaryMagnitudeSeq::sum() const { - return _sum; + return _sum.load_relaxed(); } int BinaryMagnitudeSeq::min_level() const { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp index 68f3cfba97a..1a14f930174 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHNUMBERSEQ_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHNUMBERSEQ_HPP +#include "runtime/atomic.hpp" #include "utilities/numberSeq.hpp" // HDR sequence stores the low-resolution high-dynamic-range values. @@ -59,7 +60,7 @@ public: // is not needed, it is preferred over HdrSeq. class BinaryMagnitudeSeq : public CHeapObj { private: - size_t _sum; + Atomic _sum; size_t* _mags; public: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index 9e6b1960708..7b68e6ac625 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -45,7 +45,7 @@ ShenandoahJavaThreadsIterator::ShenandoahJavaThreadsIterator(ShenandoahPhaseTimi } uint ShenandoahJavaThreadsIterator::claim() { - return AtomicAccess::fetch_then_add(&_claimed, _stride, memory_order_relaxed); + return _claimed.fetch_then_add(_stride, memory_order_relaxed); } void ShenandoahJavaThreadsIterator::threads_do(ThreadClosure* cl, uint worker_id) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp index 29d8c9fac2d..55367e706a2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -33,6 +33,7 @@ #include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "memory/iterator.hpp" +#include "runtime/atomic.hpp" #include "runtime/threads.hpp" template @@ -73,7 +74,7 @@ private: ThreadsListHandle _threads; uint const _length; uint const _stride; - volatile uint _claimed; + Atomic _claimed; ShenandoahPhaseTimings::Phase _phase; uint claim(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp index 05af25f13ad..9e160d5b294 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp @@ -1024,7 +1024,7 @@ ShenandoahRegionChunkIterator::ShenandoahRegionChunkIterator(ShenandoahHeap* hea } void ShenandoahRegionChunkIterator::reset() { - _index = 0; + _index.store_relaxed(0); } ShenandoahReconstructRememberedSetTask::ShenandoahReconstructRememberedSetTask(ShenandoahRegionIterator* regions) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp index c758873a040..c2c117e86e6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.hpp @@ -973,7 +973,7 @@ private: const size_t _total_chunks; shenandoah_padding(0); - volatile size_t _index; + Atomic _index; shenandoah_padding(1); size_t _region_index[_maximum_groups]; // The region index for the first region spanned by this group diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp index e394daa68c0..3c82efee16c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp @@ -380,14 +380,14 @@ ShenandoahScanRemembered::process_region_slice(ShenandoahHeapRegion *region, siz } inline bool ShenandoahRegionChunkIterator::has_next() const { - return _index < _total_chunks; + return _index.load_relaxed() < _total_chunks; } inline bool ShenandoahRegionChunkIterator::next(struct ShenandoahRegionChunk *assignment) { - if (_index >= _total_chunks) { + if (_index.load_relaxed() >= _total_chunks) { return false; } - size_t new_index = AtomicAccess::add(&_index, (size_t) 1, memory_order_relaxed); + size_t new_index = _index.add_then_fetch((size_t) 1, memory_order_relaxed); if (new_index > _total_chunks) { // First worker that hits new_index == _total_chunks continues, other // contending workers return false. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp index 969edafbf75..42db0b2fd2c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp @@ -30,6 +30,7 @@ #include "gc/shared/taskTerminator.hpp" #include "gc/shenandoah/shenandoahPadding.hpp" #include "nmt/memTag.hpp" +#include "runtime/atomic.hpp" #include "runtime/atomicAccess.hpp" #include "runtime/javaThread.hpp" #include "runtime/mutex.hpp" @@ -306,7 +307,7 @@ template class ParallelClaimableQueueSet: public GenericTaskQueueSet { private: shenandoah_padding(0); - volatile jint _claimed_index; + Atomic _claimed_index; shenandoah_padding(1); DEBUG_ONLY(uint _reserved; ) @@ -325,7 +326,7 @@ public: // reserve queues that not for parallel claiming void reserve(uint n) { assert(n <= size(), "Sanity"); - _claimed_index = (jint)n; + _claimed_index.store_relaxed((jint)n); DEBUG_ONLY(_reserved = n;) } @@ -336,11 +337,11 @@ template T* ParallelClaimableQueueSet::claim_next() { jint size = (jint)GenericTaskQueueSet::size(); - if (_claimed_index >= size) { + if (_claimed_index.load_relaxed() >= size) { return nullptr; } - jint index = AtomicAccess::add(&_claimed_index, 1, memory_order_relaxed); + jint index = _claimed_index.add_then_fetch(1, memory_order_relaxed); if (index <= size) { return GenericTaskQueueSet::queue((uint)index - 1); From 9454f86cfbb1917f5ec97572b8e1bc75be759db4 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 9 Mar 2026 18:05:46 +0000 Subject: [PATCH 127/170] 8379154: Refactor Selector TestNG tests to use JUnit Reviewed-by: alanb --- .../channels/SelectionKey/AtomicUpdates.java | 72 ++++---- .../channels/Selector/SelectWithConsumer.java | 173 +++++++++++------- .../nio/channels/Selector/UpdateReadyOps.java | 45 +++-- .../TestDefaultImplementation.java | 19 +- .../InheritedChannelTest.java | 31 ++-- 5 files changed, 190 insertions(+), 150 deletions(-) diff --git a/test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java b/test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java index 8e5bee51b71..e609530ff69 100644 --- a/test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java +++ b/test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test * @bug 6350055 - * @run testng AtomicUpdates + * @run junit AtomicUpdates * @summary Unit test for SelectionKey interestOpsOr and interestOpsAnd */ @@ -37,15 +37,19 @@ import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; -import org.testng.annotations.Test; + +import org.junit.jupiter.api.Test; import static java.nio.channels.SelectionKey.OP_READ; import static java.nio.channels.SelectionKey.OP_WRITE; import static java.nio.channels.SelectionKey.OP_CONNECT; import static java.nio.channels.SelectionKey.OP_ACCEPT; -import static org.testng.Assert.*; -@Test +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.fail; + public class AtomicUpdates { private SelectionKey keyFor(SocketChannel sc) { @@ -94,74 +98,69 @@ public class AtomicUpdates { } private void test(SelectionKey key) { - assertTrue(key.channel() instanceof SocketChannel); + assertInstanceOf(SocketChannel.class, key.channel()); key.interestOps(0); // 0 -> 0 int previous = key.interestOpsOr(0); - assertTrue(previous == 0); - assertTrue(key.interestOps() == 0); + assertEquals(0, previous); + assertEquals(0, key.interestOps()); // 0 -> OP_CONNECT previous = key.interestOpsOr(OP_CONNECT); - assertTrue(previous == 0); - assertTrue(key.interestOps() == OP_CONNECT); + assertEquals(0, previous); + assertEquals(OP_CONNECT, key.interestOps()); // OP_CONNECT -> OP_CONNECT previous = key.interestOpsOr(0); - assertTrue(previous == OP_CONNECT); - assertTrue(key.interestOps() == OP_CONNECT); + assertEquals(OP_CONNECT, previous); + assertEquals(OP_CONNECT, key.interestOps()); // OP_CONNECT -> OP_CONNECT | OP_READ | OP_WRITE previous = key.interestOpsOr(OP_READ | OP_WRITE); - assertTrue(previous == OP_CONNECT); - assertTrue(key.interestOps() == (OP_CONNECT | OP_READ | OP_WRITE)); + assertEquals(OP_CONNECT, previous); + assertEquals(OP_CONNECT | OP_READ | OP_WRITE, key.interestOps()); // OP_CONNECT | OP_READ | OP_WRITE -> OP_CONNECT previous = key.interestOpsAnd(~(OP_READ | OP_WRITE)); - assertTrue(previous == (OP_CONNECT | OP_READ | OP_WRITE)); - assertTrue(key.interestOps() == OP_CONNECT); + assertEquals(OP_CONNECT | OP_READ | OP_WRITE, previous); + assertEquals(OP_CONNECT, key.interestOps()); // OP_CONNECT -> 0 previous = key.interestOpsAnd(~OP_CONNECT); - assertTrue(previous == OP_CONNECT); - assertTrue(key.interestOps() == 0); + assertEquals(OP_CONNECT, previous); + assertEquals(0, key.interestOps()); // OP_READ | OP_WRITE -> OP_READ | OP_WRITE key.interestOps(OP_READ | OP_WRITE); previous = key.interestOpsAnd(~OP_ACCEPT); - assertTrue(previous == (OP_READ | OP_WRITE)); - assertTrue(key.interestOps() == (OP_READ | OP_WRITE)); + assertEquals(OP_READ | OP_WRITE, previous); + assertEquals(OP_READ | OP_WRITE, key.interestOps()); // OP_READ | OP_WRITE -> 0 previous = key.interestOpsAnd(0); - assertTrue(previous == (OP_READ | OP_WRITE)); - assertTrue(key.interestOps() == 0); + assertEquals(OP_READ | OP_WRITE, previous); + assertEquals(0, key.interestOps()); // 0 -> 0 previous = key.interestOpsAnd(0); - assertTrue(previous == 0); - assertTrue(key.interestOps() == 0); + assertEquals(0, previous); + assertEquals(0, key.interestOps()); - try { - key.interestOpsOr(OP_ACCEPT); - fail("IllegalArgumentException expected"); - } catch (IllegalArgumentException expected) { } + assertThrows(IllegalArgumentException.class, + () -> key.interestOpsOr(OP_ACCEPT)); key.cancel(); - try { - key.interestOpsOr(OP_READ); - fail("CancelledKeyException expected"); - } catch (CancelledKeyException expected) { } - try { - key.interestOpsAnd(~OP_READ); - fail("CancelledKeyException expected"); - } catch (CancelledKeyException expected) { } + assertThrows(CancelledKeyException.class, + () -> key.interestOpsOr(OP_READ)); + assertThrows(CancelledKeyException.class, + () -> key.interestOpsAnd(~OP_READ)); } /** * Test default implementation of interestOpsOr/interestOpsAnd */ + @Test public void testDefaultImplementation() throws Exception { try (SocketChannel sc = SocketChannel.open()) { SelectionKey key = keyFor(sc); @@ -172,6 +171,7 @@ public class AtomicUpdates { /** * Test the default provider implementation of SelectionKey. */ + @Test public void testNioImplementation() throws Exception { try (SocketChannel sc = SocketChannel.open(); Selector sel = Selector.open()) { diff --git a/test/jdk/java/nio/channels/Selector/SelectWithConsumer.java b/test/jdk/java/nio/channels/Selector/SelectWithConsumer.java index 1a2ada51bce..b90a68ffd04 100644 --- a/test/jdk/java/nio/channels/Selector/SelectWithConsumer.java +++ b/test/jdk/java/nio/channels/Selector/SelectWithConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,12 @@ /* @test * @summary Unit test for Selector.select/selectNow(Consumer) * @bug 8199433 8208780 - * @run testng SelectWithConsumer + * @run junit SelectWithConsumer */ /* @test * @requires (os.family == "windows") - * @run testng/othervm -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.WindowsSelectorProvider SelectWithConsumer + * @run junit/othervm -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.WindowsSelectorProvider SelectWithConsumer */ import java.io.Closeable; @@ -49,11 +49,16 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static java.util.concurrent.TimeUnit.*; -import org.testng.annotations.AfterTest; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -@Test public class SelectWithConsumer { /** @@ -81,46 +86,47 @@ public class SelectWithConsumer { // select(Consumer) notifiedOps.set(0); int n = sel.select(k -> { - assertTrue(Thread.currentThread() == callerThread); - assertTrue(k == key); + assertSame(callerThread, Thread.currentThread()); + assertSame(key, k); int readyOps = key.readyOps(); - assertTrue((readyOps & interestOps) != 0); - assertTrue((readyOps & notifiedOps.get()) == 0); + assertNotEquals(0, readyOps & interestOps); + assertEquals(0, readyOps & notifiedOps.get()); notifiedOps.set(notifiedOps.get() | readyOps); }); assertTrue((n == 1) ^ (expectedOps == 0)); - assertTrue(notifiedOps.get() == expectedOps); + assertEquals(expectedOps, notifiedOps.get()); // select(Consumer, timeout) notifiedOps.set(0); n = sel.select(k -> { - assertTrue(Thread.currentThread() == callerThread); - assertTrue(k == key); + assertSame(callerThread, Thread.currentThread()); + assertSame(key, k); int readyOps = key.readyOps(); - assertTrue((readyOps & interestOps) != 0); - assertTrue((readyOps & notifiedOps.get()) == 0); + assertNotEquals(0, readyOps & interestOps); + assertEquals(0, readyOps & notifiedOps.get()); notifiedOps.set(notifiedOps.get() | readyOps); }, 1000); assertTrue((n == 1) ^ (expectedOps == 0)); - assertTrue(notifiedOps.get() == expectedOps); + assertEquals(expectedOps, notifiedOps.get()); // selectNow(Consumer) notifiedOps.set(0); n = sel.selectNow(k -> { - assertTrue(Thread.currentThread() == callerThread); - assertTrue(k == key); + assertSame(callerThread, Thread.currentThread()); + assertSame(key, k); int readyOps = key.readyOps(); - assertTrue((readyOps & interestOps) != 0); - assertTrue((readyOps & notifiedOps.get()) == 0); + assertNotEquals(0, readyOps & interestOps); + assertEquals(0, readyOps & notifiedOps.get()); notifiedOps.set(notifiedOps.get() | readyOps); }); assertTrue((n == 1) ^ (expectedOps == 0)); - assertTrue(notifiedOps.get() == expectedOps); + assertEquals(expectedOps, notifiedOps.get()); } /** * Test that an action is performed when a channel is ready for reading. */ + @Test public void testReadable() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -142,6 +148,7 @@ public class SelectWithConsumer { /** * Test that an action is performed when a channel is ready for writing. */ + @Test public void testWritable() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -161,6 +168,7 @@ public class SelectWithConsumer { * Test that an action is performed when a channel is ready for both * reading and writing. */ + @Test public void testReadableAndWriteable() throws Exception { ServerSocketChannel ssc = null; SocketChannel sc = null; @@ -188,6 +196,7 @@ public class SelectWithConsumer { /** * Test that the action is called for two selected channels */ + @Test public void testTwoChannels() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -217,8 +226,8 @@ public class SelectWithConsumer { assertTrue(k == key1 || k == key2); counter.incrementAndGet(); }); - assertTrue(n == 2); - assertTrue(counter.get() == 2); + assertEquals(2, n); + assertEquals(2, counter.get()); // select(Consumer, timeout) counter.set(0); @@ -226,8 +235,8 @@ public class SelectWithConsumer { assertTrue(k == key1 || k == key2); counter.incrementAndGet(); }, 1000); - assertTrue(n == 2); - assertTrue(counter.get() == 2); + assertEquals(2, n); + assertEquals(2, counter.get()); // selectNow(Consumer) counter.set(0); @@ -235,8 +244,8 @@ public class SelectWithConsumer { assertTrue(k == key1 || k == key2); counter.incrementAndGet(); }); - assertTrue(n == 2); - assertTrue(counter.get() == 2); + assertEquals(2, n); + assertEquals(2, counter.get()); } finally { closePipe(p); } @@ -245,6 +254,7 @@ public class SelectWithConsumer { /** * Test calling select twice, the action should be invoked each time */ + @Test public void testRepeatedSelect1() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -269,6 +279,7 @@ public class SelectWithConsumer { * Test calling select twice. An I/O operation is performed after the * first select so the channel will not be selected by the second select. */ + @Test public void testRepeatedSelect2() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -301,6 +312,7 @@ public class SelectWithConsumer { /** * Test timeout */ + @Test public void testTimeout() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -311,7 +323,7 @@ public class SelectWithConsumer { long start = millisTime(); int n = sel.select(k -> assertTrue(false), 1000L); expectDuration(start, 500, Long.MAX_VALUE); - assertTrue(n == 0); + assertEquals(0, n); } finally { closePipe(p); } @@ -320,12 +332,13 @@ public class SelectWithConsumer { /** * Test wakeup prior to select */ + @Test public void testWakeupBeforeSelect() throws Exception { // select(Consumer) try (Selector sel = Selector.open()) { sel.wakeup(); int n = sel.select(k -> assertTrue(false)); - assertTrue(n == 0); + assertEquals(0, n); } // select(Consumer, timeout) @@ -334,19 +347,20 @@ public class SelectWithConsumer { long start = millisTime(); int n = sel.select(k -> assertTrue(false), 60*1000); expectDuration(start, 0, 20_000); - assertTrue(n == 0); + assertEquals(0, n); } } /** * Test wakeup during select */ + @Test public void testWakeupDuringSelect() throws Exception { // select(Consumer) try (Selector sel = Selector.open()) { scheduleWakeup(sel, 1, SECONDS); int n = sel.select(k -> assertTrue(false)); - assertTrue(n == 0); + assertEquals(0, n); } // select(Consumer, timeout) @@ -355,19 +369,20 @@ public class SelectWithConsumer { long start = millisTime(); int n = sel.select(k -> assertTrue(false), 60*1000); expectDuration(start, 0, 20_000); - assertTrue(n == 0); + assertEquals(0, n); } } /** * Test invoking select with interrupted status set */ + @Test public void testInterruptBeforeSelect() throws Exception { // select(Consumer) try (Selector sel = Selector.open()) { Thread.currentThread().interrupt(); int n = sel.select(k -> assertTrue(false)); - assertTrue(n == 0); + assertEquals(0, n); assertTrue(Thread.currentThread().isInterrupted()); assertTrue(sel.isOpen()); } finally { @@ -380,7 +395,7 @@ public class SelectWithConsumer { long start = millisTime(); int n = sel.select(k -> assertTrue(false), 60*1000); expectDuration(start, 0, 20_000); - assertTrue(n == 0); + assertEquals(0, n); assertTrue(Thread.currentThread().isInterrupted()); assertTrue(sel.isOpen()); } finally { @@ -391,12 +406,13 @@ public class SelectWithConsumer { /** * Test interrupt thread during select */ + @Test public void testInterruptDuringSelect() throws Exception { // select(Consumer) try (Selector sel = Selector.open()) { scheduleInterrupt(Thread.currentThread(), 1, SECONDS); int n = sel.select(k -> assertTrue(false)); - assertTrue(n == 0); + assertEquals(0, n); assertTrue(Thread.currentThread().isInterrupted()); assertTrue(sel.isOpen()); } finally { @@ -407,7 +423,7 @@ public class SelectWithConsumer { try (Selector sel = Selector.open()) { scheduleInterrupt(Thread.currentThread(), 1, SECONDS); int n = sel.select(k -> assertTrue(false), 60*1000); - assertTrue(n == 0); + assertEquals(0, n); assertTrue(Thread.currentThread().isInterrupted()); assertTrue(sel.isOpen()); } finally { @@ -418,34 +434,38 @@ public class SelectWithConsumer { /** * Test invoking select on a closed selector */ - @Test(expectedExceptions = ClosedSelectorException.class) + @Test public void testClosedSelector1() throws Exception { Selector sel = Selector.open(); sel.close(); - sel.select(k -> assertTrue(false)); + assertThrows(ClosedSelectorException.class, + () -> sel.select(k -> assertTrue(false))); } - @Test(expectedExceptions = ClosedSelectorException.class) + @Test public void testClosedSelector2() throws Exception { Selector sel = Selector.open(); sel.close(); - sel.select(k -> assertTrue(false), 1000); + assertThrows(ClosedSelectorException.class, + () -> sel.select(k -> assertTrue(false), 1000)); } - @Test(expectedExceptions = ClosedSelectorException.class) + @Test public void testClosedSelector3() throws Exception { Selector sel = Selector.open(); sel.close(); - sel.selectNow(k -> assertTrue(false)); + assertThrows(ClosedSelectorException.class, + () -> sel.selectNow(k -> assertTrue(false))); } /** * Test closing selector while in a selection operation */ + @Test public void testCloseDuringSelect() throws Exception { // select(Consumer) try (Selector sel = Selector.open()) { scheduleClose(sel, 3, SECONDS); int n = sel.select(k -> assertTrue(false)); - assertTrue(n == 0); + assertEquals(0, n); assertFalse(sel.isOpen()); } @@ -458,7 +478,7 @@ public class SelectWithConsumer { long after = System.nanoTime(); long selectDuration = (after - start) / 1000000; long scheduleDuration = (start - before) / 1000000; - assertTrue(n == 0); + assertEquals(0, n); assertTrue(selectDuration > 2000 && selectDuration < 10*1000, "select took " + selectDuration + " ms schedule took " + scheduleDuration + " ms"); @@ -469,7 +489,7 @@ public class SelectWithConsumer { /** * Test action closing selector */ - @Test(expectedExceptions = ClosedSelectorException.class) + @Test public void testActionClosingSelector() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -482,12 +502,14 @@ public class SelectWithConsumer { sink.write(messageBuffer()); // should relay ClosedSelectorException - sel.select(k -> { - assertTrue(k == key); - try { - sel.close(); - } catch (IOException ioe) { } - }); + assertThrows(ClosedSelectorException.class, + () -> sel.select(k -> { + assertTrue(k == key); + try { + sel.close(); + } catch (IOException ioe) { } + }) + ); } finally { closePipe(p); } @@ -497,6 +519,7 @@ public class SelectWithConsumer { * Test that the action is invoked while synchronized on the selector and * its selected-key set. */ + @Test public void testLocks() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -510,7 +533,7 @@ public class SelectWithConsumer { // select(Consumer) sel.select(k -> { - assertTrue(k == key); + assertSame(key, k); assertTrue(Thread.holdsLock(sel)); assertFalse(Thread.holdsLock(sel.keys())); assertTrue(Thread.holdsLock(sel.selectedKeys())); @@ -518,7 +541,7 @@ public class SelectWithConsumer { // select(Consumer, timeout) sel.select(k -> { - assertTrue(k == key); + assertSame(key, k); assertTrue(Thread.holdsLock(sel)); assertFalse(Thread.holdsLock(sel.keys())); assertTrue(Thread.holdsLock(sel.selectedKeys())); @@ -526,7 +549,7 @@ public class SelectWithConsumer { // selectNow(Consumer) sel.selectNow(k -> { - assertTrue(k == key); + assertSame(key, k); assertTrue(Thread.holdsLock(sel)); assertFalse(Thread.holdsLock(sel.keys())); assertTrue(Thread.holdsLock(sel.selectedKeys())); @@ -540,6 +563,7 @@ public class SelectWithConsumer { * Test that selection operations remove cancelled keys from the selector's * key and selected-key sets. */ + @Test public void testCancel() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -569,7 +593,7 @@ public class SelectWithConsumer { // cancel key1 key1.cancel(); int n = sel.selectNow(k -> assertTrue(k == key2)); - assertTrue(n == 1); + assertEquals(1, n); assertFalse(sel.keys().contains(key1)); assertTrue(sel.keys().contains(key2)); assertFalse(sel.selectedKeys().contains(key1)); @@ -578,7 +602,7 @@ public class SelectWithConsumer { // cancel key2 key2.cancel(); n = sel.selectNow(k -> assertTrue(false)); - assertTrue(n == 0); + assertEquals(0, n); assertFalse(sel.keys().contains(key1)); assertFalse(sel.keys().contains(key2)); assertFalse(sel.selectedKeys().contains(key1)); @@ -591,6 +615,7 @@ public class SelectWithConsumer { /** * Test an action invoking select() */ + @Test public void testReentrantSelect1() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -611,7 +636,7 @@ public class SelectWithConsumer { } catch (IllegalStateException expected) { } }); - assertTrue(n == 1); + assertEquals(1, n); } finally { closePipe(p); } @@ -620,6 +645,7 @@ public class SelectWithConsumer { /** * Test an action invoking selectNow() */ + @Test public void testReentrantSelect2() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -640,7 +666,7 @@ public class SelectWithConsumer { } catch (IllegalStateException expected) { } }); - assertTrue(n == 1); + assertEquals(1, n); } finally { closePipe(p); } @@ -649,6 +675,7 @@ public class SelectWithConsumer { /** * Test an action invoking select(Consumer) */ + @Test public void testReentrantSelect3() throws Exception { Pipe p = Pipe.open(); try (Selector sel = Selector.open()) { @@ -669,7 +696,7 @@ public class SelectWithConsumer { } catch (IllegalStateException expected) { } }); - assertTrue(n == 1); + assertEquals(1, n); } finally { closePipe(p); } @@ -678,42 +705,46 @@ public class SelectWithConsumer { /** * Negative timeout */ - @Test(expectedExceptions = IllegalArgumentException.class) + @Test public void testNegativeTimeout() throws Exception { try (Selector sel = Selector.open()) { - sel.select(k -> { }, -1L); + assertThrows(IllegalArgumentException.class, + () -> sel.select(k -> { }, -1L)); } } /** * Null action */ - @Test(expectedExceptions = NullPointerException.class) + @Test public void testNull1() throws Exception { try (Selector sel = Selector.open()) { - sel.select(null); + assertThrows(NullPointerException.class, + () -> sel.select(null)); } } - @Test(expectedExceptions = NullPointerException.class) + @Test public void testNull2() throws Exception { try (Selector sel = Selector.open()) { - sel.select(null, 1000); + assertThrows(NullPointerException.class, + () -> sel.select(null, 1000)); } } - @Test(expectedExceptions = NullPointerException.class) + @Test public void testNull3() throws Exception { try (Selector sel = Selector.open()) { - sel.selectNow(null); + assertThrows(NullPointerException.class, + () -> sel.selectNow(null)); } } // -- support methods --- - private final ScheduledExecutorService POOL = Executors.newScheduledThreadPool(1); + private static final ScheduledExecutorService POOL = Executors.newScheduledThreadPool(1); - @AfterTest - void shutdownThreadPool() { + @AfterAll + static void shutdownThreadPool() { POOL.shutdown(); } diff --git a/test/jdk/java/nio/channels/Selector/UpdateReadyOps.java b/test/jdk/java/nio/channels/Selector/UpdateReadyOps.java index 57a563c6a59..87b512fe495 100644 --- a/test/jdk/java/nio/channels/Selector/UpdateReadyOps.java +++ b/test/jdk/java/nio/channels/Selector/UpdateReadyOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @run testng UpdateReadyOps + * @run junit UpdateReadyOps * @summary Test that the ready set from a selection operation is bitwise-disjoined * into a key's ready set when the key is already in the selected-key set */ @@ -37,16 +37,19 @@ import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -@Test public class UpdateReadyOps { /** * Test that OP_WRITE is preserved when updating the ready set of a key in * the selected-key set to add OP_READ. */ + @Test public void testOpWritePreserved() throws Exception { try (ConnectionPair pair = new ConnectionPair(); Selector sel = Selector.open()) { @@ -58,14 +61,14 @@ public class UpdateReadyOps { SelectionKey key = sc1.register(sel, SelectionKey.OP_WRITE); int updated = sel.select(); - assertTrue(updated == 1); + assertEquals(1, updated); assertTrue(sel.selectedKeys().contains(key)); assertFalse(key.isReadable()); assertTrue(key.isWritable()); // select again, should be no updates updated = sel.select(); - assertTrue(updated == 0); + assertEquals(0, updated); assertTrue(sel.selectedKeys().contains(key)); assertFalse(key.isReadable()); assertTrue(key.isWritable()); @@ -78,16 +81,17 @@ public class UpdateReadyOps { key.interestOps(SelectionKey.OP_READ); updated = sel.select(); - assertTrue(updated == 1); - assertTrue(sel.selectedKeys().size() == 1); + assertEquals(1, updated); + assertEquals(1, sel.selectedKeys().size()); assertTrue(key.isReadable()); assertTrue(key.isWritable()); - assertTrue(key.readyOps() == (SelectionKey.OP_READ|SelectionKey.OP_WRITE)); + assertEquals(SelectionKey.OP_READ|SelectionKey.OP_WRITE, + key.readyOps()); // select again, should be no updates updated = sel.select(); - assertTrue(updated == 0); - assertTrue(sel.selectedKeys().size() == 1); + assertEquals(0, updated); + assertEquals(1, sel.selectedKeys().size()); assertTrue(key.isReadable()); assertTrue(key.isWritable()); } @@ -97,6 +101,7 @@ public class UpdateReadyOps { * Test that OP_READ is preserved when updating the ready set of a key in * the selected-key set to add OP_WRITE. */ + @Test public void testOpReadPreserved() throws Exception { try (ConnectionPair pair = new ConnectionPair(); Selector sel = Selector.open()) { @@ -111,32 +116,32 @@ public class UpdateReadyOps { sc2.write(helloMessage()); int updated = sel.select(); - assertTrue(updated == 1); - assertTrue(sel.selectedKeys().size() == 1); + assertEquals(1, updated); + assertEquals(1, sel.selectedKeys().size()); assertTrue(sel.selectedKeys().contains(key)); assertTrue(key.isReadable()); assertFalse(key.isWritable()); // select again, should be no updates updated = sel.select(); - assertTrue(updated == 0); + assertEquals(0, updated); assertTrue(sel.selectedKeys().contains(key)); assertTrue(key.isReadable()); assertFalse(key.isWritable()); key.interestOps(SelectionKey.OP_WRITE); updated = sel.select(); - assertTrue(updated == 1); - assertTrue(sel.selectedKeys().size() == 1); + assertEquals(1, updated); + assertEquals(1, sel.selectedKeys().size()); assertTrue(sel.selectedKeys().contains(key)); assertTrue(key.isReadable()); assertTrue(key.isWritable()); - assertTrue(key.readyOps() == (SelectionKey.OP_READ|SelectionKey.OP_WRITE)); + assertEquals(SelectionKey.OP_READ|SelectionKey.OP_WRITE, key.readyOps()); // select again, should be no updates updated = sel.select(); - assertTrue(updated == 0); - assertTrue(sel.selectedKeys().size() == 1); + assertEquals(0, updated); + assertEquals(1, sel.selectedKeys().size()); assertTrue(key.isReadable()); assertTrue(key.isWritable()); } diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/TestDefaultImplementation.java b/test/jdk/java/nio/channels/spi/SelectorProvider/TestDefaultImplementation.java index 6d402949982..e17b16dadc7 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/TestDefaultImplementation.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/TestDefaultImplementation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,22 @@ * @test * @bug 8254692 * @summary Basic test for java.nio.channels.spi.SelectorProvider.java default implementation - * @run testng TestDefaultImplementation + * @run junit TestDefaultImplementation */ -import org.testng.annotations.Test; - import java.io.IOException; import java.net.ProtocolFamily; -import java.nio.channels.*; +import java.nio.channels.DatagramChannel; +import java.nio.channels.Pipe; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; import java.nio.channels.spi.AbstractSelector; import java.nio.channels.spi.SelectorProvider; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertThrows; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; public class TestDefaultImplementation { static final Class UOE = UnsupportedOperationException.class; @@ -67,4 +70,4 @@ public class TestDefaultImplementation { @Override public ServerSocketChannel openServerSocketChannel() { return null; } @Override public SocketChannel openSocketChannel() { return null; } } -} \ No newline at end of file +} diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java index 934bf509d88..897fc6236dc 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * UnixSocketTest StateTest StateTestService EchoTest EchoService * UnixDomainChannelTest CloseTest Launcher Util * CheckIPv6Test CheckIPv6Service - * @run testng/othervm/native InheritedChannelTest + * @run junit/othervm/native InheritedChannelTest * @key intermittent */ @@ -45,14 +45,16 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Stream; import jdk.test.lib.JDKToolFinder; import jdk.test.lib.Utils; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.Platform; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static java.util.Arrays.asList; @@ -64,19 +66,18 @@ public class InheritedChannelTest { private static final Path libraryPath = Paths.get(System.getProperty("java.library.path")); - @DataProvider - public Object[][] testCases() { - return new Object[][] { - { "UnixDomainChannelTest", List.of(UnixDomainChannelTest.class.getName())}, - { "UnixSocketTest", List.of(UnixSocketTest.class.getName())}, - { "StateTest", List.of(StateTest.class.getName(), "-Dtest.classes="+TEST_CLASSES)}, - { "EchoTest", List.of(EchoTest.class.getName()) }, - { "CheckIPv6Test", List.of(CheckIPv6Test.class.getName()) }, - { "CloseTest", List.of(CloseTest.class.getName()) }, - }; + public static Stream testCases() { + return Stream.of + (Arguments.of( "UnixDomainChannelTest", List.of(UnixDomainChannelTest.class.getName())), + Arguments.of( "UnixSocketTest", List.of(UnixSocketTest.class.getName())), + Arguments.of( "StateTest", List.of(StateTest.class.getName(), "-Dtest.classes="+TEST_CLASSES)), + Arguments.of( "EchoTest", List.of(EchoTest.class.getName())), + Arguments.of( "CheckIPv6Test", List.of(CheckIPv6Test.class.getName())), + Arguments.of( "CloseTest", List.of(CloseTest.class.getName()))); } - @Test(dataProvider = "testCases") + @ParameterizedTest + @MethodSource("testCases") public void test(String desc, List opts) throws Throwable { String pathVar = Platform.sharedLibraryPathVariableName(); System.out.println(pathVar + "=" + libraryPath); From 6b921835124904f0fe6d807daab81a6d1b89b560 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 9 Mar 2026 18:06:14 +0000 Subject: [PATCH 128/170] 8378879: Refactor java/nio/channels/Channels TestNG tests to use JUnit Reviewed-by: alanb --- .../nio/channels/Channels/EncodingTest.java | 113 +++++++++--------- .../nio/channels/Channels/ReadXBytes.java | 76 ++++++------ .../Channels/SocketChannelStreams.java | 110 ++++++++++------- .../nio/channels/Channels/TransferTo.java | 54 ++++----- .../nio/channels/Channels/TransferTo2.java | 39 +++--- .../nio/channels/Channels/TransferToBase.java | 14 +-- .../Channels/TransferTo_2GB_transferFrom.java | 6 +- .../Channels/TransferTo_2GB_transferTo.java | 6 +- 8 files changed, 226 insertions(+), 192 deletions(-) diff --git a/test/jdk/java/nio/channels/Channels/EncodingTest.java b/test/jdk/java/nio/channels/Channels/EncodingTest.java index 1f2530ae41b..341439524c1 100644 --- a/test/jdk/java/nio/channels/Channels/EncodingTest.java +++ b/test/jdk/java/nio/channels/Channels/EncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,16 +34,21 @@ import java.nio.charset.Charset; import java.nio.charset.MalformedInputException; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * @test * @bug 8183743 * @summary Test to verify the new overload method with Charset functions the same * as the existing method that takes a charset name. - * @run testng EncodingTest + * @run junit EncodingTest */ public class EncodingTest { static final int ITERATIONS = 2; @@ -73,53 +78,50 @@ public class EncodingTest { } } - String testFile = Paths.get(USER_DIR, "channelsEncodingTest.txt").toString(); - String testIllegalInput = Paths.get(USER_DIR, "channelsIllegalInputTest.txt").toString(); - String testIllegalOutput = Paths.get(USER_DIR, "channelsIllegalOutputTest.txt").toString(); + static String testFile = Paths.get(USER_DIR, "channelsEncodingTest.txt").toString(); + static String testIllegalInput = Paths.get(USER_DIR, "channelsIllegalInputTest.txt").toString(); + static String testIllegalOutput = Paths.get(USER_DIR, "channelsIllegalOutputTest.txt").toString(); /* * DataProvider for read and write test. * Writes and reads with the same encoding */ - @DataProvider(name = "writeAndRead") - public Object[][] getWRParameters() { - return new Object[][]{ - {testFile, StandardCharsets.ISO_8859_1.name(), null, - StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1}, - {testFile, null, StandardCharsets.ISO_8859_1, - StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1}, - {testFile, StandardCharsets.UTF_8.name(), null, - StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8}, - {testFile, null, StandardCharsets.UTF_8, - StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8} - }; + public static Stream writeAndRead() { + return Stream.of + (Arguments.of(testFile, StandardCharsets.ISO_8859_1.name(), null, + StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1), + Arguments.of(testFile, null, StandardCharsets.ISO_8859_1, + StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1), + Arguments.of(testFile, StandardCharsets.UTF_8.name(), null, + StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8), + Arguments.of(testFile, null, StandardCharsets.UTF_8, + StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8) + ); } /* * DataProvider for illegal input test * Writes the data in ISO8859 and reads with UTF8, expects MalformedInputException */ - @DataProvider(name = "illegalInput") - public Object[][] getParameters() { - return new Object[][]{ - {testIllegalInput, StandardCharsets.ISO_8859_1.name(), null, StandardCharsets.UTF_8.name(), null}, - {testIllegalInput, StandardCharsets.ISO_8859_1.name(), null, null, StandardCharsets.UTF_8}, - {testIllegalInput, null, StandardCharsets.ISO_8859_1, StandardCharsets.UTF_8.name(), null}, - {testIllegalInput, null, StandardCharsets.ISO_8859_1, null, StandardCharsets.UTF_8}, - }; + public static Stream illegalInput() { + return Stream.of + (Arguments.of(testIllegalInput, StandardCharsets.ISO_8859_1.name(), null, StandardCharsets.UTF_8.name(), null), + Arguments.of(testIllegalInput, StandardCharsets.ISO_8859_1.name(), null, null, StandardCharsets.UTF_8), + Arguments.of(testIllegalInput, null, StandardCharsets.ISO_8859_1, StandardCharsets.UTF_8.name(), null), + Arguments.of(testIllegalInput, null, StandardCharsets.ISO_8859_1, null, StandardCharsets.UTF_8) + ); } /* * DataProvider for illegal output test * Attemps to write some malformed chars, expects MalformedInputException */ - @DataProvider(name = "illegalOutput") - public Object[][] getWriteParameters() { - return new Object[][]{ - {testIllegalOutput, StandardCharsets.UTF_8.name(), null}, - {testIllegalOutput, null, StandardCharsets.UTF_8} - }; + public static Stream illegalOutput() { + return Stream.of + (Arguments.of(testIllegalOutput, StandardCharsets.UTF_8.name(), null), + Arguments.of(testIllegalOutput, null, StandardCharsets.UTF_8) + ); } /** @@ -140,7 +142,8 @@ public class EncodingTest { * @param charsetReader the charset for creating the reader * @throws Exception */ - @Test(dataProvider = "writeAndRead") + @ParameterizedTest + @MethodSource("writeAndRead") public void testWriteAndRead(String file, String csnWriter, Charset charsetWriter, String csnReader, Charset charsetReader) throws Exception { writeToFile(data, file, csnWriter, charsetWriter); @@ -148,7 +151,7 @@ public class EncodingTest { String result1 = readFileToString(file, csnReader, null); String result2 = readFileToString(file, null, charsetReader); - Assert.assertEquals(result1, result2); + assertEquals(result1, result2); } /** @@ -162,11 +165,14 @@ public class EncodingTest { * @param charsetReader the charset for creating the reader * @throws Exception */ - @Test(dataProvider = "illegalInput", expectedExceptions = MalformedInputException.class) + @ParameterizedTest + @MethodSource( "illegalInput") void testMalformedInput(String file, String csnWriter, Charset charsetWriter, - String csnReader, Charset charsetReader) throws Exception { + String csnReader, Charset charsetReader) + throws Exception { writeToFile(data, file, csnWriter, charsetWriter); - readFileToString(file, csnReader, charsetReader); + assertThrows(MalformedInputException.class, + () -> readFileToString(file, csnReader, charsetReader)); } /** @@ -178,23 +184,22 @@ public class EncodingTest { * @param charset the charset * @throws Exception */ - @Test(dataProvider = "illegalOutput", expectedExceptions = MalformedInputException.class) + @ParameterizedTest + @MethodSource("illegalOutput") public void testMalformedOutput(String fileName, String csn, Charset charset) - throws Exception { + throws Exception { try (FileOutputStream fos = new FileOutputStream(fileName); - WritableByteChannel wbc = (WritableByteChannel) fos.getChannel();) { - Writer writer; - if (csn != null) { - writer = Channels.newWriter(wbc, csn); - } else { - writer = Channels.newWriter(wbc, charset); - } - - for (int i = 0; i < ITERATIONS; i++) { - writer.write(illChars); - } - writer.flush(); - writer.close(); + WritableByteChannel wbc = (WritableByteChannel) fos.getChannel();) { + Charset cs = (csn != null) ? Charset.forName(csn) : charset; + Writer writer = Channels.newWriter(wbc, cs); + assertThrows(MalformedInputException.class, () -> { + try (writer) { + for (int i = 0; i < ITERATIONS; i++) { + writer.write(illChars); + } + writer.flush(); + } + }); } } diff --git a/test/jdk/java/nio/channels/Channels/ReadXBytes.java b/test/jdk/java/nio/channels/Channels/ReadXBytes.java index 1ea500f355d..4b296bb021e 100644 --- a/test/jdk/java/nio/channels/Channels/ReadXBytes.java +++ b/test/jdk/java/nio/channels/Channels/ReadXBytes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * @library /test/lib * @build jdk.test.lib.RandomFactory * @modules java.base/jdk.internal.util - * @run testng/othervm/timeout=900 -Xmx12G ReadXBytes + * @run junit/othervm/timeout=900 -Xmx12g ReadXBytes * @key randomness */ import java.io.File; @@ -48,20 +48,24 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Random; +import java.util.stream.IntStream; import jdk.internal.util.ArraysSupport; import static java.nio.file.StandardOpenOption.*; import jdk.test.lib.RandomFactory; -import org.testng.Assert; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class ReadXBytes { @@ -193,7 +197,7 @@ public class ReadXBytes { (length, cis) -> { byte[] bytes = cis.readAllBytes(); assertNotNull(bytes); - assertEquals(bytes.length, 0L); + assertEquals(0, bytes.length); } ); } @@ -206,7 +210,7 @@ public class ReadXBytes { cis.skipNBytes(length); byte[] bytes = cis.readAllBytes(); assertNotNull(bytes); - assertEquals(bytes.length, 0); + assertEquals(0, bytes.length); } ); } @@ -218,9 +222,9 @@ public class ReadXBytes { (length, cis, fis) -> { byte[] cisBytes = cis.readAllBytes(); assertNotNull(cisBytes); - assertEquals(cisBytes.length, (long)length); + assertEquals(length, cisBytes.length); byte[] fisBytes = fis.readAllBytes(); - assertEquals(cisBytes, fisBytes); + assertArrayEquals(fisBytes, cisBytes); } ); } @@ -236,20 +240,19 @@ public class ReadXBytes { ); } - // Provides an array of lengths - @DataProvider - public Object[][] lengthProvider() throws IOException { - return new Object[][] { - {1 + RAND.nextInt(1)}, - {1 + RAND.nextInt(Byte.MAX_VALUE)}, - {1 + RAND.nextInt(Short.MAX_VALUE)}, - {1 + RAND.nextInt(1_000_000)}, - {1 + RAND.nextInt(BIG_LENGTH)} - }; + // Provides a stream of lengths + public static IntStream fileLengths() throws IOException { + return IntStream.of + (1 + RAND.nextInt(1), + 1 + RAND.nextInt(Byte.MAX_VALUE), + 1 + RAND.nextInt(Short.MAX_VALUE), + 1 + RAND.nextInt(1_000_000), + 1 + RAND.nextInt(BIG_LENGTH)); } // Verifies readAllBytes() accuracy for random lengths and initial positions - @Test(dataProvider = "lengthProvider") + @ParameterizedTest + @MethodSource("fileLengths") public void readAllBytes(int len) throws IOException { dataTest(len, (length) -> createFileWithRandomContent(length), (length, cis, fis) -> { @@ -257,10 +260,10 @@ public class ReadXBytes { cis.skipNBytes(position); byte[] cisBytes = cis.readAllBytes(); assertNotNull(cisBytes); - assertEquals(cisBytes.length, length - position); + assertEquals(length - position, cisBytes.length); fis.skipNBytes(position); byte[] fisBytes = fis.readAllBytes(); - assertEquals(cisBytes, fisBytes); + assertArrayEquals(fisBytes, cisBytes); } ); } @@ -285,7 +288,7 @@ public class ReadXBytes { (length, cis) -> { byte[] bytes = cis.readNBytes(1); assertNotNull(bytes); - assertEquals(bytes.length, 0); + assertEquals(0, bytes.length); } ); } @@ -298,7 +301,7 @@ public class ReadXBytes { cis.skipNBytes(length); byte[] bytes = cis.readNBytes(1); assertNotNull(bytes); - assertEquals(bytes.length, 0); + assertEquals(0, bytes.length); } ); } @@ -310,9 +313,9 @@ public class ReadXBytes { (length, cis, fis) -> { byte[] cisBytes = cis.readNBytes(BIG_LENGTH); assertNotNull(cisBytes); - assertEquals(cisBytes.length, (long)length); + assertEquals(length, cisBytes.length); byte[] fisBytes = fis.readNBytes(BIG_LENGTH); - assertEquals(cisBytes, fisBytes); + assertArrayEquals(fisBytes, cisBytes); } ); } @@ -327,16 +330,17 @@ public class ReadXBytes { cis.skipNBytes(BIG_LENGTH); byte[] cisBytes = cis.readNBytes(n); assertNotNull(cisBytes); - assertEquals(cisBytes.length, n); + assertEquals(n, cisBytes.length); fis.skipNBytes(BIG_LENGTH); byte[] fisBytes = fis.readNBytes(n); - assertEquals(cisBytes, fisBytes); + assertArrayEquals(fisBytes, cisBytes); } ); } // Verifies readNBytes() accuracy for random lengths and initial positions - @Test(dataProvider = "lengthProvider") + @ParameterizedTest + @MethodSource("fileLengths") public void readNBytes(int len) throws IOException { dataTest(len, (length) -> createFileWithRandomContent(length), (length, cis, fis) -> { @@ -346,10 +350,10 @@ public class ReadXBytes { cis.skipNBytes(position); byte[] cisBytes = cis.readNBytes(n); assertNotNull(cisBytes); - assertEquals(cisBytes.length, n); + assertEquals(n, cisBytes.length); fis.skipNBytes(position); byte[] fisBytes = fis.readNBytes(n); - assertEquals(cisBytes, fisBytes); + assertArrayEquals(fisBytes, cisBytes); } ); } diff --git a/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java b/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java index 519de1e725f..0eab36dc3ee 100644 --- a/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java +++ b/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @bug 8279339 8371718 * @summary Exercise InputStream/OutputStream returned by Channels.newXXXStream * when channel is a SocketChannel - * @run testng SocketChannelStreams + * @run junit SocketChannelStreams */ import java.io.Closeable; @@ -48,101 +48,112 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.testng.annotations.*; -import static org.testng.Assert.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; -@Test public class SocketChannelStreams { // Maximum size of internal temporary buffer private static final int MAX_BUFFER_SIZE = 128*1024; - private ScheduledExecutorService executor; + private static ScheduledExecutorService executor; - @BeforeClass() - public void init() { + @BeforeAll() + public static void init() { executor = Executors.newSingleThreadScheduledExecutor(); } - @AfterClass - public void finish() { + @AfterAll + public static void finish() { executor.shutdown(); } /** * Test read when bytes are available. */ + @Test public void testRead1() throws Exception { withConnection((sc, peer) -> { write(peer, 99); int n = Channels.newInputStream(sc).read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test read blocking before bytes are available. */ + @Test public void testRead2() throws Exception { withConnection((sc, peer) -> { scheduleWrite(peer, 99, 1000); int n = Channels.newInputStream(sc).read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test read after peer has closed connection. */ + @Test public void testRead3() throws Exception { withConnection((sc, peer) -> { peer.close(); int n = Channels.newInputStream(sc).read(); - assertEquals(n, -1); + assertEquals(-1, n); }); } /** * Test read blocking before peer closes connection. */ + @Test public void testRead4() throws Exception { withConnection((sc, peer) -> { scheduleClose(peer, 1000); int n = Channels.newInputStream(sc).read(); - assertEquals(n, -1); + assertEquals(-1, n); }); } /** * Test async close of channel when thread blocked in read. */ + @Test public void testRead5() throws Exception { withConnection((sc, peer) -> { scheduleClose(sc, 2000); InputStream in = Channels.newInputStream(sc); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); }); } /** * Test async close of input stream, when thread blocked in read. */ + @Test public void testRead6() throws Exception { withConnection((sc, peer) -> { InputStream in = Channels.newInputStream(sc); scheduleClose(in, 2000); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); }); } /** * Test interrupted status set before read. */ + @Test public void testRead7() throws Exception { withConnection((sc, peer) -> { Thread.currentThread().interrupt(); try { InputStream in = Channels.newInputStream(sc); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); } finally { Thread.interrupted(); // clear interrupt } @@ -153,12 +164,13 @@ public class SocketChannelStreams { /** * Test interrupt of thread blocked in read. */ + @Test public void testRead8() throws Exception { withConnection((sc, peer) -> { Future interrupter = scheduleInterrupt(Thread.currentThread(), 2000); try { InputStream in = Channels.newInputStream(sc); - expectThrows(IOException.class, () -> in.read()); + assertThrows(IOException.class, () -> in.read()); } finally { interrupter.cancel(true); Thread.interrupted(); // clear interrupt @@ -170,35 +182,38 @@ public class SocketChannelStreams { /** * Test that read is untimed when SO_TIMEOUT is set on the Socket adaptor. */ + @Test public void testRead9() throws Exception { withConnection((sc, peer) -> { sc.socket().setSoTimeout(100); scheduleWrite(peer, 99, 2000); // read should block until bytes are available int b = Channels.newInputStream(sc).read(); - assertTrue(b == 99); + assertEquals(99, b); }); } /** * Test write. */ + @Test public void testWrite1() throws Exception { withConnection((sc, peer) -> { OutputStream out = Channels.newOutputStream(sc); out.write(99); int n = read(peer); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test async close of channel when thread blocked in write. */ + @Test public void testWrite2() throws Exception { withConnection((sc, peer) -> { scheduleClose(sc, 2000); - expectThrows(IOException.class, () -> { + assertThrows(IOException.class, () -> { OutputStream out = Channels.newOutputStream(sc); byte[] data = new byte[64*1000]; while (true) { @@ -211,11 +226,12 @@ public class SocketChannelStreams { /** * Test async close of output stream when thread blocked in write. */ + @Test public void testWrite3() throws Exception { withConnection((sc, peer) -> { OutputStream out = Channels.newOutputStream(sc); scheduleClose(out, 2000); - expectThrows(IOException.class, () -> { + assertThrows(IOException.class, () -> { byte[] data = new byte[64*1000]; while (true) { out.write(data); @@ -227,12 +243,13 @@ public class SocketChannelStreams { /** * Test interrupted status set before write. */ + @Test public void testWrite4() throws Exception { withConnection((sc, peer) -> { Thread.currentThread().interrupt(); try { OutputStream out = Channels.newOutputStream(sc); - expectThrows(IOException.class, () -> out.write(99)); + assertThrows(IOException.class, () -> out.write(99)); } finally { Thread.interrupted(); // clear interrupt } @@ -243,11 +260,12 @@ public class SocketChannelStreams { /** * Test interrupt of thread blocked in write. */ + @Test public void testWrite5() throws Exception { withConnection((sc, peer) -> { Future interrupter = scheduleInterrupt(Thread.currentThread(), 2000); try { - expectThrows(IOException.class, () -> { + assertThrows(IOException.class, () -> { OutputStream out = Channels.newOutputStream(sc); byte[] data = new byte[64*1000]; while (true) { @@ -266,6 +284,7 @@ public class SocketChannelStreams { * Test read when another thread is blocked in write. The read should * complete immediately. */ + @Test public void testConcurrentReadWrite1() throws Exception { withConnection((sc, peer) -> { InputStream in = Channels.newInputStream(sc); @@ -283,7 +302,7 @@ public class SocketChannelStreams { // test read, should not be blocked by writer thread write(peer, 99); int n = in.read(); - assertEquals(n, 99); + assertEquals(99, n); }); } @@ -291,6 +310,7 @@ public class SocketChannelStreams { * Test read when another thread is blocked in write. The read should * block until bytes are available. */ + @Test public void testConcurrentReadWrite2() throws Exception { withConnection((sc, peer) -> { InputStream in = Channels.newInputStream(sc); @@ -308,13 +328,14 @@ public class SocketChannelStreams { // test read, should not be blocked by writer thread scheduleWrite(peer, 99, 500); int n = in.read(); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test writing when another thread is blocked in read. */ + @Test public void testConcurrentReadWrite3() throws Exception { withConnection((sc, peer) -> { InputStream in = Channels.newInputStream(sc); @@ -329,74 +350,79 @@ public class SocketChannelStreams { // test write, should not be blocked by reader thread out.write(99); int n = read(peer); - assertEquals(n, 99); + assertEquals(99, n); }); } /** * Test read/write when channel configured non-blocking. */ + @Test public void testIllegalBlockingMode() throws Exception { withConnection((sc, peer) -> { InputStream in = Channels.newInputStream(sc); OutputStream out = Channels.newOutputStream(sc); sc.configureBlocking(false); - expectThrows(IllegalBlockingModeException.class, () -> in.read()); - expectThrows(IllegalBlockingModeException.class, () -> out.write(99)); + assertThrows(IllegalBlockingModeException.class, () -> in.read()); + assertThrows(IllegalBlockingModeException.class, () -> out.write(99)); }); } /** * Test NullPointerException. */ + @Test public void testNullPointerException() throws Exception { withConnection((sc, peer) -> { InputStream in = Channels.newInputStream(sc); OutputStream out = Channels.newOutputStream(sc); - expectThrows(NullPointerException.class, () -> in.read(null)); - expectThrows(NullPointerException.class, () -> in.read(null, 0, 0)); + assertThrows(NullPointerException.class, () -> in.read(null)); + assertThrows(NullPointerException.class, () -> in.read(null, 0, 0)); - expectThrows(NullPointerException.class, () -> out.write(null)); - expectThrows(NullPointerException.class, () -> out.write(null, 0, 0)); + assertThrows(NullPointerException.class, () -> out.write(null)); + assertThrows(NullPointerException.class, () -> out.write(null, 0, 0)); }); } /** * Test IndexOutOfBoundsException. */ + @Test public void testIndexOutOfBoundsException() throws Exception { withConnection((sc, peer) -> { InputStream in = Channels.newInputStream(sc); OutputStream out = Channels.newOutputStream(sc); byte[] ba = new byte[100]; - expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, -1, 1)); - expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 0, -1)); - expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 0, 1000)); - expectThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 1, 100)); + assertThrows(IndexOutOfBoundsException.class, () -> in.read(ba, -1, 1)); + assertThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 0, -1)); + assertThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 0, 1000)); + assertThrows(IndexOutOfBoundsException.class, () -> in.read(ba, 1, 100)); - expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, -1, 1)); - expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 0, -1)); - expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 0, 1000)); - expectThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 1, 100)); + assertThrows(IndexOutOfBoundsException.class, () -> out.write(ba, -1, 1)); + assertThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 0, -1)); + assertThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 0, 1000)); + assertThrows(IndexOutOfBoundsException.class, () -> out.write(ba, 1, 100)); }); } /** * Test that internal buffers have at most MAX_BUFFER_SIZE bytes remaining. */ + @Test public void testReadLimit() throws IOException { InputStream in = Channels.newInputStream(new TestChannel()); byte[] b = new byte[3*MAX_BUFFER_SIZE]; int n = in.read(b, 0, b.length); - assertEquals(n, MAX_BUFFER_SIZE); + assertEquals(MAX_BUFFER_SIZE, n); } /** * Test that internal buffers have at most MAX_BUFFER_SIZE bytes remaining. */ + @Test public void testWriteLimit() throws IOException { OutputStream out = Channels.newOutputStream(new TestChannel()); byte[] b = new byte[3*MAX_BUFFER_SIZE]; diff --git a/test/jdk/java/nio/channels/Channels/TransferTo.java b/test/jdk/java/nio/channels/Channels/TransferTo.java index b02bf7b3649..a9626978dbe 100644 --- a/test/jdk/java/nio/channels/Channels/TransferTo.java +++ b/test/jdk/java/nio/channels/Channels/TransferTo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,17 +37,20 @@ import java.nio.file.Path; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.stream.Stream; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; -import static org.testng.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test * @library /test/lib * @build jdk.test.lib.RandomFactory - * @run testng/othervm/timeout=720 TransferTo + * @run junit/othervm/timeout=720 TransferTo * @bug 8265891 * @summary Tests whether sun.nio.ChannelInputStream.transferTo conforms to the * InputStream.transferTo specification @@ -59,41 +62,37 @@ public class TransferTo extends TransferToBase { * Provides test scenarios, i.e., combinations of input and output streams * to be tested. */ - @DataProvider - public static Object[][] streamCombinations() { - return new Object[][] { - // tests FileChannel.transferTo(FileChannel) optimized case - {fileChannelInput(), fileChannelOutput()}, + public static Stream streamCombinations() { + return Stream.of + (// tests FileChannel.transferTo(FileChannel) optimized case + Arguments.of(fileChannelInput(), fileChannelOutput()), - // tests FileChannel.transferTo(SelectableChannelOutput) - // optimized case - {fileChannelInput(), selectableChannelOutput()}, + // tests FileChannel.transferTo(SelectableChannelOutput) + // optimized case + Arguments.of(fileChannelInput(), selectableChannelOutput()), - // tests FileChannel.transferTo(WritableByteChannelOutput) - // optimized case - {fileChannelInput(), writableByteChannelOutput()}, + // tests FileChannel.transferTo(WritableByteChannelOutput) + // optimized case + Arguments.of(fileChannelInput(), writableByteChannelOutput()), - // tests InputStream.transferTo(OutputStream) default case - {readableByteChannelInput(), defaultOutput()} - }; + // tests InputStream.transferTo(OutputStream) default case + Arguments.of(readableByteChannelInput(), defaultOutput())); } /* * Input streams to be tested. */ - @DataProvider - public static Object[][] inputStreamProviders() { - return new Object[][] { - {fileChannelInput()}, - {readableByteChannelInput()} - }; + public static Stream inputStreamProviders() { + return Stream.of(Arguments.of(fileChannelInput()), + Arguments.of(readableByteChannelInput())); } /* * Testing API compliance: input stream must throw NullPointerException * when parameter "out" is null. */ - @Test(dataProvider = "inputStreamProviders") + @ParameterizedTest + @MethodSource("inputStreamProviders") public void testNullPointerException(InputStreamProvider inputStreamProvider) { assertNullPointerException(inputStreamProvider); } @@ -102,7 +101,8 @@ public class TransferTo extends TransferToBase { * Testing API compliance: complete content of input stream must be * transferred to output stream. */ - @Test(dataProvider = "streamCombinations") + @ParameterizedTest + @MethodSource("streamCombinations") public void testStreamContents(InputStreamProvider inputStreamProvider, OutputStreamProvider outputStreamProvider) throws Exception { assertStreamContents(inputStreamProvider, outputStreamProvider); diff --git a/test/jdk/java/nio/channels/Channels/TransferTo2.java b/test/jdk/java/nio/channels/Channels/TransferTo2.java index bd7e13c3a9b..0e02803c8d3 100644 --- a/test/jdk/java/nio/channels/Channels/TransferTo2.java +++ b/test/jdk/java/nio/channels/Channels/TransferTo2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,11 @@ import java.io.OutputStream; import java.io.IOException; import java.nio.channels.Channels; import java.nio.channels.Pipe; +import java.util.stream.Stream; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static java.lang.String.format; @@ -35,7 +37,7 @@ import static java.lang.String.format; * @test * @library /test/lib * @build jdk.test.lib.RandomFactory - * @run testng/othervm/timeout=180 TransferTo2 + * @run junit/othervm/timeout=180 TransferTo2 * @bug 8278268 * @summary Tests FileChannel.transferFrom() optimized case * @key randomness @@ -46,33 +48,29 @@ public class TransferTo2 extends TransferToBase { * Provides test scenarios, i.e., combinations of input and output streams * to be tested. */ - @DataProvider - public static Object[][] streamCombinations() { - return new Object[][] { - // tests FileChannel.transferFrom(SelectableChannelOutput) optimized case - {selectableChannelInput(), fileChannelOutput()}, + public static Stream streamCombinations() { + return Stream.of + (// tests FileChannel.transferFrom(SelectableChannelOutput) optimized case + Arguments.of(selectableChannelInput(), fileChannelOutput()), - // tests FileChannel.transferFrom(ReadableByteChannelInput) optimized case - {readableByteChannelInput(), fileChannelOutput()}, - }; + // tests FileChannel.transferFrom(ReadableByteChannelInput) optimized case + Arguments.of(readableByteChannelInput(), fileChannelOutput())); } /* * Input streams to be tested. */ - @DataProvider - public static Object[][] inputStreamProviders() { - return new Object[][] { - {selectableChannelInput()}, - {readableByteChannelInput()} - }; + public static Stream inputStreamProviders() { + return Stream.of(Arguments.of(selectableChannelInput()), + Arguments.of(readableByteChannelInput())); } /* * Testing API compliance: input stream must throw NullPointerException * when parameter "out" is null. */ - @Test(dataProvider = "inputStreamProviders") + @ParameterizedTest + @MethodSource("inputStreamProviders") public void testNullPointerException(InputStreamProvider inputStreamProvider) { assertNullPointerException(inputStreamProvider); } @@ -81,7 +79,8 @@ public class TransferTo2 extends TransferToBase { * Testing API compliance: complete content of input stream must be * transferred to output stream. */ - @Test(dataProvider = "streamCombinations") + @ParameterizedTest + @MethodSource("streamCombinations") public void testStreamContents(InputStreamProvider inputStreamProvider, OutputStreamProvider outputStreamProvider) throws Exception { assertStreamContents(inputStreamProvider, outputStreamProvider); diff --git a/test/jdk/java/nio/channels/Channels/TransferToBase.java b/test/jdk/java/nio/channels/Channels/TransferToBase.java index 53ca283ae78..482fb1f262c 100644 --- a/test/jdk/java/nio/channels/Channels/TransferToBase.java +++ b/test/jdk/java/nio/channels/Channels/TransferToBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,9 +43,9 @@ import jdk.test.lib.RandomFactory; import static java.lang.String.format; import static java.nio.file.StandardOpenOption.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; class TransferToBase { static final int MIN_SIZE = 10_000; @@ -88,7 +88,7 @@ class TransferToBase { long reported = in.transferTo(out); int count = inBytes.length - posIn; - assertEquals(reported, count, format("reported %d bytes but should report %d", reported, count)); + assertEquals(count, reported); byte[] outBytes = recorder.get().get(); assertTrue(Arrays.equals(inBytes, posIn, posIn + count, outBytes, posOut, posOut + count), @@ -238,11 +238,11 @@ class TransferToBase { // compare reported transferred bytes, must be 3 GB // less the value of the initial position - assertEquals(count, BYTES_WRITTEN - initPos); + assertEquals(BYTES_WRITTEN - initPos, count); } // compare content of both files, failing if different - assertEquals(Files.mismatch(sourceFile, targetFile), -1); + assertEquals(-1, Files.mismatch(sourceFile, targetFile)); } finally { Files.delete(targetFile); diff --git a/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferFrom.java b/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferFrom.java index f57d6cca963..1dc17f6f5fc 100644 --- a/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferFrom.java +++ b/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferFrom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,13 @@ import java.nio.file.Files; import static java.nio.file.StandardOpenOption.*; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; /* * @test * @library /test/lib * @build jdk.test.lib.RandomFactory - * @run testng/othervm/timeout=720 TransferTo_2GB_transferFrom + * @run junit/othervm/timeout=720 TransferTo_2GB_transferFrom * @bug 8278268 * @summary Tests if ChannelInputStream.transferFrom correctly * transfers 2GB+ using FileChannel.transferFrom(ReadableByteChannel). diff --git a/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferTo.java b/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferTo.java index fdd3bddb126..174b89bd988 100644 --- a/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferTo.java +++ b/test/jdk/java/nio/channels/Channels/TransferTo_2GB_transferTo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,13 +29,13 @@ import java.nio.file.Files; import static java.nio.file.StandardOpenOption.*; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; /* * @test * @library /test/lib * @build jdk.test.lib.RandomFactory - * @run testng/othervm/timeout=720 TransferTo_2GB_transferTo + * @run junit/othervm/timeout=720 TransferTo_2GB_transferTo * @bug 8265891 * @summary Tests if ChannelInputStream.transferTo correctly * transfers 2GB+ using FileChannel.transferTo(WritableByteChannel). From 93634b5665c97c321294623627f542c264f63dc5 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 9 Mar 2026 18:06:35 +0000 Subject: [PATCH 129/170] 8379153: Refactor java/nio/channels/File{Channel,Lock} TestNG tests to use JUnit Reviewed-by: alanb, dfuchs --- .../FileChannel/MapToMemorySegmentTest.java | 17 ++--- .../nio/channels/FileChannel/Transfer.java | 63 ++++++++--------- .../channels/FileChannel/Transfer4GBFile.java | 20 +++--- .../FileChannel/TransferTo6GBFile.java | 16 +++-- .../java/nio/channels/FileLock/Overlaps.java | 70 ++++++++++--------- 5 files changed, 91 insertions(+), 95 deletions(-) diff --git a/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java b/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java index de89e318fc3..bd2097176ca 100644 --- a/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java +++ b/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* @test * @bug 8281412 * @summary Test FileChannel::map to MemorySegment with custom file channel - * @run testng/othervm MapToMemorySegmentTest + * @run junit/othervm MapToMemorySegmentTest */ import java.io.File; @@ -39,10 +39,10 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.file.Path; import java.nio.file.StandardOpenOption; -import org.testng.annotations.Test; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; public class MapToMemorySegmentTest { @@ -58,13 +58,14 @@ public class MapToMemorySegmentTest { } } - @Test(expectedExceptions = UnsupportedOperationException.class) + @Test public void testCustomFileChannel() throws IOException { var arena = Arena.ofConfined(); var fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ); var fileChannel = new CustomFileChannel(fc); - try (arena; fileChannel){ - fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena); + try (arena; fileChannel) { + assertThrows(UnsupportedOperationException.class, + () -> fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena)); } } diff --git a/test/jdk/java/nio/channels/FileChannel/Transfer.java b/test/jdk/java/nio/channels/FileChannel/Transfer.java index 51adba60b06..1afc38a61bd 100644 --- a/test/jdk/java/nio/channels/FileChannel/Transfer.java +++ b/test/jdk/java/nio/channels/FileChannel/Transfer.java @@ -27,7 +27,7 @@ * @library .. * @library /test/lib * @build jdk.test.lib.RandomFactory - * @run testng/timeout=300 Transfer + * @run junit/timeout=300 Transfer * @key randomness */ @@ -54,8 +54,13 @@ import java.util.concurrent.TimeUnit; import jdk.test.lib.RandomFactory; -import org.testng.Assert; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class Transfer { @@ -83,25 +88,22 @@ public class Transfer { long oldSourcePosition = sourceChannel.position(); long bytesWritten = sinkChannel.transferFrom(sourceChannel, 0, 10); - if (bytesWritten != 10) - throw new RuntimeException("Transfer failed"); + assertEquals(10, bytesWritten, "Transfer failed"); - if (sourceChannel.position() == oldSourcePosition) - throw new RuntimeException("Source position didn't change"); + assertNotEquals(oldSourcePosition, sourceChannel.position(), + "Source position didn't change"); - if (sinkChannel.position() != oldSinkPosition) - throw new RuntimeException("Sink position changed"); + assertEquals(oldSinkPosition, sinkChannel.position(), + "Sink position changed"); - if (sinkChannel.size() != 10) - throw new RuntimeException("Unexpected sink size"); + assertEquals(10, sinkChannel.size(), "Unexpected sink size"); bytesWritten = sinkChannel.transferFrom(sourceChannel, 1000, 10); - if (bytesWritten > 10) - throw new RuntimeException("Wrote too many bytes"); + assertFalse(bytesWritten > 10, "Wrote too many bytes"); - if (sinkChannel.size() != 1000 + bytesWritten) - throw new RuntimeException("Unexpected sink size"); + assertEquals(1000 + bytesWritten, sinkChannel.size(), + "Unexpected sink size"); sourceChannel.close(); sinkChannel.close(); @@ -130,8 +132,7 @@ public class Transfer { int totalWritten = 0; while (totalWritten < size + 10) { int written = sink.write(outgoingdata); - if (written < 0) - throw new Exception("Write failed"); + assertTrue(written >= 0, "Write failed"); totalWritten += written; } @@ -143,14 +144,11 @@ public class Transfer { long bytesWritten = fc.transferFrom(source, 0, size); fc.force(true); - if (bytesWritten != size) - throw new RuntimeException("Transfer failed"); + assertEquals(size, bytesWritten, "Transfer failed"); - if (fc.position() != oldPosition) - throw new RuntimeException("Position changed"); + assertEquals(oldPosition, fc.position(), "Position changed"); - if (fc.size() != size) - throw new RuntimeException("Unexpected sink size "+ fc.size()); + assertEquals(size, fc.size(), "Unexpected sink size "+ fc.size()); fc.close(); sink.close(); @@ -168,7 +166,7 @@ public class Transfer { CharSequence csq = "Reality is greater than the sum of its parts."; Files.writeString(source.toPath(), csq); final long length = csq.length(); - Assert.assertEquals(source.length(), length); + assertEquals(length, source.length()); File target = File.createTempFile("before", "after"); target.deleteOnExit(); @@ -183,7 +181,7 @@ public class Transfer { long n = chSource.transferTo(length, 16385, chTarget); // At the end of the input so no bytes should be transferred - Assert.assertEquals(n, 0); + assertEquals(0, n); } } @@ -251,8 +249,7 @@ public class Transfer { fc1.transferTo(0, srcData.length + 1, fc2); - if (fc2.size() > 4) - throw new Exception("xferTest03 failed"); + assertFalse(fc2.size() > 4, "xferTest03 failed"); fc1.close(); fc2.close(); @@ -273,9 +270,7 @@ public class Transfer { while ((c = r.read()) != -1) sb.append((char)c); String contents = sb.toString(); - if (! contents.equals(expected)) - throw new Exception("expected: " + expected - + ", got: " + contents); + assertEquals(expected, contents); r.close(); } @@ -301,8 +296,7 @@ public class Transfer { new RandomAccessFile(sink, "rw").getChannel(); long n = sinkChannel.transferFrom(sourceChannel, 0L, sourceChannel.size()); // overflow - if (n != remaining) - throw new Exception("n == " + n + ", remaining == " + remaining); + assertEquals(remaining, n); sinkChannel.close(); sourceChannel.close(); @@ -363,9 +357,8 @@ public class Transfer { FileChannel fc1 = new FileOutputStream(source).getChannel(); FileChannel fc2 = new RandomAccessFile(target, "rw").getChannel(); try { - fc2.transferFrom(fc1, 0L, 0); - throw new RuntimeException("NonReadableChannelException expected"); - } catch (NonReadableChannelException expected) { + assertThrows(NonReadableChannelException.class, + () -> fc2.transferFrom(fc1, 0L, 0)); } finally { fc1.close(); fc2.close(); diff --git a/test/jdk/java/nio/channels/FileChannel/Transfer4GBFile.java b/test/jdk/java/nio/channels/FileChannel/Transfer4GBFile.java index b8c026c983c..0766f4ffb45 100644 --- a/test/jdk/java/nio/channels/FileChannel/Transfer4GBFile.java +++ b/test/jdk/java/nio/channels/FileChannel/Transfer4GBFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @bug 4638365 * @summary Test FileChannel.transferFrom and transferTo for 4GB files * @build FileChannelUtils - * @run testng/timeout=300 Transfer4GBFile + * @run junit/timeout=300 Transfer4GBFile */ import java.io.BufferedWriter; @@ -38,10 +38,12 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.concurrent.TimeUnit; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import static java.nio.file.StandardOpenOption.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class Transfer4GBFile { private static PrintStream err = System.err; @@ -71,10 +73,8 @@ public class Transfer4GBFile { long bytesWritten = sourceChannel.transferTo(testSize - 40, 10, sinkChannel); - if (bytesWritten != 10) { - throw new RuntimeException("Transfer test 4 failed " + - bytesWritten); - } + assertEquals(10, bytesWritten, + "Transfer test 4 failed " + bytesWritten); } Files.delete(source); @@ -112,10 +112,8 @@ public class Transfer4GBFile { FileChannel sinkChannel = FileChannel.open(sink, WRITE)) { long bytesWritten = sinkChannel.transferFrom(sourceChannel, testSize - 40, 10); - if (bytesWritten != 10) { - throw new RuntimeException("Transfer test 5 failed " + - bytesWritten); - } + assertEquals(10, bytesWritten, + "Transfer test 5 failed " + bytesWritten); } Files.delete(source); diff --git a/test/jdk/java/nio/channels/FileChannel/TransferTo6GBFile.java b/test/jdk/java/nio/channels/FileChannel/TransferTo6GBFile.java index 9ca6df0c870..791a0718a75 100644 --- a/test/jdk/java/nio/channels/FileChannel/TransferTo6GBFile.java +++ b/test/jdk/java/nio/channels/FileChannel/TransferTo6GBFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @bug 6253145 * @summary Test FileChannel.transferTo with file positions up to 8GB * @build FileChannelUtils - * @run testng/timeout=300 TransferTo6GBFile + * @run junit/timeout=300 TransferTo6GBFile */ import java.io.IOException; @@ -40,10 +40,14 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.concurrent.TimeUnit; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import static java.nio.file.StandardOpenOption.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class TransferTo6GBFile { private static PrintStream err = System.err; @@ -126,16 +130,14 @@ public class TransferTo6GBFile { long nread = 0; while (nread < count) { int n = source.read(readbuf); - if (n < 0) - throw new RuntimeException("Premature EOF!"); + assertTrue(n >= 0, "Premature EOF!"); nread += n; } // check reply from echo server readbuf.flip(); sendbuf.flip(); - if (!readbuf.equals(sendbuf)) - throw new RuntimeException("Echoed bytes do not match!"); + assertEquals(sendbuf, readbuf, "Echoed bytes do not match!"); readbuf.clear(); sendbuf.clear(); } diff --git a/test/jdk/java/nio/channels/FileLock/Overlaps.java b/test/jdk/java/nio/channels/FileLock/Overlaps.java index 64293e2996d..3e3b92ac67e 100644 --- a/test/jdk/java/nio/channels/FileLock/Overlaps.java +++ b/test/jdk/java/nio/channels/FileLock/Overlaps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 5041655 * @summary Verify FileLock.overlaps - * @run testng Overlaps + * @run junit Overlaps */ import java.io.IOException; import java.nio.ByteBuffer; @@ -33,15 +33,18 @@ import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.Files; import java.nio.file.Path; +import java.util.stream.Stream; import static java.lang.Boolean.*; import static java.nio.file.StandardOpenOption.*; -import static org.testng.Assert.assertEquals; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; public class Overlaps { private static final long POS = 27; @@ -49,47 +52,46 @@ public class Overlaps { private static FileChannel fc; - @BeforeClass - public void before() throws IOException { + @BeforeAll + public static void before() throws IOException { Path path = Files.createTempFile(Path.of("."), "foo", ".bar"); fc = FileChannel.open(path, CREATE, WRITE, DELETE_ON_CLOSE); fc.position(POS); fc.write(ByteBuffer.wrap(new byte[(int)SIZE])); } - @AfterClass - public void after() throws IOException { + @AfterAll + public static void after() throws IOException { fc.close(); } - @DataProvider - public Object[][] ranges() { - return new Object[][] { - {POS, SIZE, -1,-1, FALSE}, - {POS, SIZE, 0, -1, FALSE}, - {POS, SIZE, POS - 1, -1, FALSE}, - {POS, SIZE, POS + SIZE/2, -1, FALSE}, - {POS, SIZE, POS + SIZE, -1, FALSE}, - {POS, SIZE, -1, POS, FALSE}, - {POS, SIZE, -1, POS + SIZE/2, TRUE}, - {POS, SIZE, POS - 2, 1, FALSE}, - {POS, SIZE, POS + 1, 1, TRUE}, - {POS, SIZE, POS + SIZE/2, 0, TRUE}, - {POS, SIZE, Long.MAX_VALUE, 2, FALSE}, - {POS, SIZE, POS + SIZE / 2, Long.MAX_VALUE, TRUE}, - {POS, SIZE, 0, 0, TRUE}, - {Long.MAX_VALUE - SIZE/2, 0, 0, SIZE, FALSE}, - {Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE/4, SIZE, TRUE}, - {Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE, 0, TRUE}, - {Long.MAX_VALUE - SIZE, 0, Long.MAX_VALUE - SIZE/2, 0, TRUE} - }; + public static Stream ranges() { + return Stream.of( + Arguments.of(POS, SIZE, -1, -1, FALSE), + Arguments.of(POS, SIZE, 0, -1, FALSE), + Arguments.of(POS, SIZE, POS - 1, -1, FALSE), + Arguments.of(POS, SIZE, POS + SIZE/2, -1, FALSE), + Arguments.of(POS, SIZE, POS + SIZE, -1, FALSE), + Arguments.of(POS, SIZE, -1, POS, FALSE), + Arguments.of(POS, SIZE, -1, POS + SIZE/2, TRUE), + Arguments.of(POS, SIZE, POS - 2, 1, FALSE), + Arguments.of(POS, SIZE, POS + 1, 1, TRUE), + Arguments.of(POS, SIZE, POS + SIZE/2, 0, TRUE), + Arguments.of(POS, SIZE, Long.MAX_VALUE, 2, FALSE), + Arguments.of(POS, SIZE, POS + SIZE / 2, Long.MAX_VALUE, TRUE), + Arguments.of(POS, SIZE, 0, 0, TRUE), + Arguments.of(Long.MAX_VALUE - SIZE/2, 0, 0, SIZE, FALSE), + Arguments.of(Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE/4, SIZE, TRUE), + Arguments.of(Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE, 0, TRUE), + Arguments.of(Long.MAX_VALUE - SIZE, 0, Long.MAX_VALUE - SIZE/2, 0, TRUE)); } - @Test(dataProvider = "ranges") + @ParameterizedTest + @MethodSource("ranges") public void overlaps(long lockPos, long lockSize, long pos, long size, boolean overlaps) throws IOException { try (FileLock lock = fc.lock(lockPos, lockSize, false)) { - assertEquals(lock.overlaps(pos, size), overlaps); + assertEquals(overlaps, lock.overlaps(pos, size)); } } } From a95799d62fc0ec8e8fcdfd62813273c6896845ef Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 9 Mar 2026 19:32:47 +0000 Subject: [PATCH 130/170] 8379229: Remove AppContext from javax.swing.JComponent Reviewed-by: psadhukhan, serb --- .../share/classes/javax/swing/JComponent.java | 62 ++++------- .../awt/dnd/BadSerializationTest/badAction | Bin 3651 -> 3651 bytes .../java/awt/dnd/BadSerializationTest/good | Bin 3457 -> 3651 bytes .../awt/dnd/BadSerializationTest/noEvents | Bin 3160 -> 3160 bytes .../dnd/BadSerializationTest/nullComponent | Bin 3470 -> 3470 bytes .../dnd/BadSerializationTest/nullDragSource | Bin 3609 -> 3609 bytes .../awt/dnd/BadSerializationTest/nullOrigin | Bin 3605 -> 3605 bytes .../swing/JComponent/8043610/bug8043610.java | 102 ------------------ 8 files changed, 19 insertions(+), 145 deletions(-) delete mode 100644 test/jdk/javax/swing/JComponent/8043610/bug8043610.java diff --git a/src/java.desktop/share/classes/javax/swing/JComponent.java b/src/java.desktop/share/classes/javax/swing/JComponent.java index 6351522ab49..87d6a41c2b0 100644 --- a/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -31,6 +31,7 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.FocusTraversalPolicy; import java.awt.Font; import java.awt.FontMetrics; @@ -261,16 +262,6 @@ public abstract class JComponent extends Container implements Serializable, */ static boolean DEBUG_GRAPHICS_LOADED; - /** - * Key used to look up a value from the AppContext to determine the - * JComponent the InputVerifier is running for. That is, if - * AppContext.get(INPUT_VERIFIER_SOURCE_KEY) returns non-null, it - * indicates the EDT is calling into the InputVerifier from the - * returned component. - */ - private static final Object INPUT_VERIFIER_SOURCE_KEY = - new StringBuilder("InputVerifierSourceKey"); - /* The following fields support set methods for the corresponding * java.awt.Component properties. */ @@ -414,8 +405,7 @@ public abstract class JComponent extends Container implements Serializable, /** ActionMap. */ private ActionMap actionMap; - /** Key used to store the default locale in an AppContext **/ - private static final String defaultLocale = "JComponent.defaultLocale"; + private static volatile Locale defaultLocale; private static Component componentObtainingGraphicsFrom; private static Object componentObtainingGraphicsFromLock = new @@ -2841,12 +2831,12 @@ public abstract class JComponent extends Container implements Serializable, * @since 1.4 */ public static Locale getDefaultLocale() { - Locale l = (Locale) SwingUtilities.appContextGet(defaultLocale); - if( l == null ) { + Locale l = defaultLocale; + if (l == null) { //REMIND(bcb) choosing the default value is more complicated //than this. l = Locale.getDefault(); - JComponent.setDefaultLocale( l ); + JComponent.setDefaultLocale(l); } return l; } @@ -2865,8 +2855,8 @@ public abstract class JComponent extends Container implements Serializable, * @see #setLocale * @since 1.4 */ - public static void setDefaultLocale( Locale l ) { - SwingUtilities.appContextPut(defaultLocale, l); + public static void setDefaultLocale(Locale l) { + defaultLocale = l; } @@ -3507,7 +3497,7 @@ public abstract class JComponent extends Container implements Serializable, // This class is used by the KeyboardState class to provide a single - // instance that can be stored in the AppContext. + // instance. static final class IntVector { int[] array = null; int count = 0; @@ -3538,24 +3528,12 @@ public abstract class JComponent extends Container implements Serializable, } } + private static final IntVector intVector = new IntVector(); @SuppressWarnings("serial") static class KeyboardState implements Serializable { - private static final Object keyCodesKey = - JComponent.KeyboardState.class; - - // Get the array of key codes from the AppContext. - static IntVector getKeyCodeArray() { - IntVector iv = - (IntVector)SwingUtilities.appContextGet(keyCodesKey); - if (iv == null) { - iv = new IntVector(); - SwingUtilities.appContextPut(keyCodesKey, iv); - } - return iv; - } static void registerKeyPressed(int keyCode) { - IntVector kca = getKeyCodeArray(); + IntVector kca = intVector; int count = kca.size(); int i; for(i=0;isb692r8zYBi{;A-#hYyx*=3{i{WC{)59M1KI833h=3Yh=^ delta 29 lcmX>sb692r8zYDP+TDi)e`ihJ%*W`?$rKd2Ih^YaGXSW13a$VE diff --git a/test/jdk/java/awt/dnd/BadSerializationTest/good b/test/jdk/java/awt/dnd/BadSerializationTest/good index 523df353a1aad149c7110bb0c45d509c9a55d5cb..f5dd0e2cb5bd8cd009c2023c1b66bffdde19f74e 100644 GIT binary patch delta 378 zcmZpaJ}k3=jgdn$|5WhW!w1VY^D*YKdFUtS=jtUE6y&7p3u;K&q7(Ab`C90)YB-G2P*opI1_>;*wgFS(cg- z>KT+;oL^d$oC*?t*M04dMT=N3$iN~7d61nIdc~8CId;effQ{w_kp(3TygsGLnJI}1 z?nQ}tDXA5cE7%Qq;V$?OR5O{MvqdB{xP*bBgn=nF4s(?LUck&VT8rA|JD4x8P2r`6$0VHBl05;Zi5}&bvc|iqGT{#O#t^x=ErUEbA diff --git a/test/jdk/java/awt/dnd/BadSerializationTest/noEvents b/test/jdk/java/awt/dnd/BadSerializationTest/noEvents index a45ba168c71de59fcc1b27af7eee1cc081de77dc..fdf1125889fc3ab000cc035b2ccfcdcddd917c50 100644 GIT binary patch delta 29 lcmca1aYJGQ8zYBi{;A-#hYyx*=3{i{WC{)59L~ka1OTUW3C{ok delta 29 lcmca1aYJGQ8zYDP+TDi)e`ihJ%*W`?$rKd2Ih>1;2>_~N3FH6( diff --git a/test/jdk/java/awt/dnd/BadSerializationTest/nullComponent b/test/jdk/java/awt/dnd/BadSerializationTest/nullComponent index 63aee01cc2ce59e126e5d2cf3ad52040a7df9e2b..d5dfcada90cfec9e9a4758e4f7c527998929a453 100644 GIT binary patch delta 29 lcmeB^?vvhdnu$X*|5WhW!w1VYUuJUWWC{)5EW=a82mrIU3j_cF delta 29 lcmeB^?vvhdnu)`H?e0T@zq2N9zRcv#$rKd2S%#;G5dgNP3mE_a diff --git a/test/jdk/java/awt/dnd/BadSerializationTest/nullDragSource b/test/jdk/java/awt/dnd/BadSerializationTest/nullDragSource index a483f7106a8ad1779dfb54593277fbe2183fafea..efdfeb3ed20a4cff964f112ecb5507507efbaf77 100644 GIT binary patch delta 29 lcmbO!GgD>*8zYBi{;A-#hYyx*=3{i{WC{)59L{x!833FI3L5|b delta 29 lcmbO!GgD>*8zYDP+TDi)e`ihJ%*W`?$rKd2Ih^YdGXS3U3NQcw diff --git a/test/jdk/java/awt/dnd/BadSerializationTest/nullOrigin b/test/jdk/java/awt/dnd/BadSerializationTest/nullOrigin index 5af1996e74b38800dcfeb62184d0181e738fef40..17d9fd3a1a9f6a232a7c6a1b8fe56b9b1080c42c 100644 GIT binary patch delta 29 lcmbO#GgW2-8zYBi{;A-#hYyx*=3{i{WC{)59L}|m833Cf3J(AP delta 29 lcmbO#GgW2-8zYDP+TDi)e`ihJ%*W`?$rKd2Ih<=BGXS0r3M2pk diff --git a/test/jdk/javax/swing/JComponent/8043610/bug8043610.java b/test/jdk/javax/swing/JComponent/8043610/bug8043610.java deleted file mode 100644 index 7eb371d1a0e..00000000000 --- a/test/jdk/javax/swing/JComponent/8043610/bug8043610.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/** - * @test - * @key headful - * @bug 8043610 - * @summary Tests that JComponent invalidate, revalidate and repaint methods could - * be called from any thread - * @author Petr Pchelko - * @modules java.desktop/sun.awt - */ - -import sun.awt.SunToolkit; - -import javax.swing.*; -import java.awt.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicReference; - -public class bug8043610 { - private static volatile JFrame frame; - private static volatile JComponent component; - - public static void main(String[] args) throws Exception { - ThreadGroup stubTG = new ThreadGroup(getRootThreadGroup(), "Stub Thread Group"); - ThreadGroup swingTG = new ThreadGroup(getRootThreadGroup(), "SwingTG"); - try { - Thread stubThread = new Thread(stubTG, SunToolkit::createNewAppContext); - stubThread.start(); - stubThread.join(); - - CountDownLatch startSwingLatch = new CountDownLatch(1); - new Thread(swingTG, () -> { - SunToolkit.createNewAppContext(); - SwingUtilities.invokeLater(() -> { - frame = new JFrame(); - component = new JLabel("Test Text"); - frame.add(component); - frame.setBounds(100, 100, 100, 100); - frame.setVisible(true); - startSwingLatch.countDown(); - }); - }).start(); - startSwingLatch.await(); - - AtomicReference caughtException = new AtomicReference<>(); - Thread checkThread = new Thread(getRootThreadGroup(), () -> { - try { - component.invalidate(); - component.revalidate(); - component.repaint(new Rectangle(0, 0, 0, 0)); - } catch (Exception e) { - caughtException.set(e); - } - }); - checkThread.start(); - checkThread.join(); - - if (caughtException.get() != null) { - throw new RuntimeException("Failed. Caught exception!", caughtException.get()); - } - } finally { - new Thread(swingTG, () -> SwingUtilities.invokeLater(() -> { - if (frame != null) { - frame.dispose(); - } - })).start(); - } - } - - private static ThreadGroup getRootThreadGroup() { - ThreadGroup currentTG = Thread.currentThread().getThreadGroup(); - ThreadGroup parentTG = currentTG.getParent(); - while (parentTG != null) { - currentTG = parentTG; - parentTG = currentTG.getParent(); - } - return currentTG; - } -} From 46a5ed9908eb3aeafa1eb95a28114199d4b4c1e3 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 9 Mar 2026 19:33:03 +0000 Subject: [PATCH 131/170] 8379137: Remove AppContext from javax.swing.JOptionPane Reviewed-by: serb, psadhukhan --- .../classes/javax/swing/JOptionPane.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/JOptionPane.java b/src/java.desktop/share/classes/javax/swing/JOptionPane.java index 707b9febf10..c41400b9b37 100644 --- a/src/java.desktop/share/classes/javax/swing/JOptionPane.java +++ b/src/java.desktop/share/classes/javax/swing/JOptionPane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1656,7 +1656,7 @@ public class JOptionPane extends JComponent implements Accessible return getDesktopPaneForComponent(parentComponent.getParent()); } - private static final Object sharedFrameKey = JOptionPane.class; + private static volatile Frame sharedRootFrame; /** * Sets the frame to use for class methods in which a frame is @@ -1668,11 +1668,7 @@ public class JOptionPane extends JComponent implements Accessible * @param newRootFrame the default Frame to use */ public static void setRootFrame(Frame newRootFrame) { - if (newRootFrame != null) { - SwingUtilities.appContextPut(sharedFrameKey, newRootFrame); - } else { - SwingUtilities.appContextRemove(sharedFrameKey); - } + sharedRootFrame = newRootFrame; } /** @@ -1687,13 +1683,10 @@ public class JOptionPane extends JComponent implements Accessible * @see java.awt.GraphicsEnvironment#isHeadless */ public static Frame getRootFrame() throws HeadlessException { - Frame sharedFrame = - (Frame)SwingUtilities.appContextGet(sharedFrameKey); - if (sharedFrame == null) { - sharedFrame = SwingUtilities.getSharedOwnerFrame(); - SwingUtilities.appContextPut(sharedFrameKey, sharedFrame); + if (sharedRootFrame == null) { + sharedRootFrame = SwingUtilities.getSharedOwnerFrame(); } - return sharedFrame; + return sharedRootFrame; } /** From 6a8e9530fe914fb7a328ea41f7e57c8cb5e6e99d Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Mon, 9 Mar 2026 21:58:50 +0000 Subject: [PATCH 132/170] 8379442: GenShen: Fix two errors introduced by 29039 Reviewed-by: xpeng, serb, wkemper --- .../gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp | 2 +- src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index ac8b3ebdf37..a1aeb918553 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -739,7 +739,7 @@ size_t ShenandoahAdaptiveHeuristics::accelerated_consumption(double& acceleratio if (i > 0) { // first sample not included in weighted average because it has no weight. double sample_weight = x_array[i] - x_array[i-1]; - weighted_y_sum = y_array[i] * sample_weight; + weighted_y_sum += y_array[i] * sample_weight; total_weight += sample_weight; } y_sum += y_array[i]; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index c39e2e7bb79..d765f33fee0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -2848,7 +2848,7 @@ size_t ShenandoahFreeSet::reserve_regions(size_t to_reserve, size_t to_reserve_o _partitions.leftmost(ShenandoahFreeSetPartitionId::OldCollector), _partitions.rightmost(ShenandoahFreeSetPartitionId::OldCollector)); old_region_count++; - assert(ac = ShenandoahHeapRegion::region_size_bytes(), "Cannot move to old unless entire region is in alloc capacity"); + assert(ac == ShenandoahHeapRegion::region_size_bytes(), "Cannot move to old unless entire region is in alloc capacity"); mutator_allocatable_words -= ShenandoahHeapRegion::region_size_words(); continue; } From 6a061f9d2529117ad3e0fa7a2a58e5d8032a2ea2 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Mon, 9 Mar 2026 22:54:52 +0000 Subject: [PATCH 133/170] 8379426: [macos] jpackage: runtime bundle version suffix is out of sync with the version property in the Info.plist file Reviewed-by: almatvee --- .../jpackage/internal/ActiveKeychainList.java | 144 ++++++++++ .../internal/AppImageInfoPListFile.java | 65 ----- .../internal/MacApplicationBuilder.java | 79 +++-- .../jdk/jpackage/internal/MacFromOptions.java | 36 ++- .../internal/MacPackagingPipeline.java | 2 +- .../jdk/jpackage/internal/TempKeychain.java | 103 ------- .../jpackage/internal/ApplicationBuilder.java | 31 ++ .../jdk/jpackage/internal/Globals.java | 19 ++ .../jdk/jpackage/test/JPackageCommand.java | 14 +- .../internal/ActiveKeychainListTest.java | 269 ++++++++++++++++++ .../jpackage/internal/MacDmgPackagerTest.java | 7 +- .../tools/jpackage/junit/macosx/junit.java | 11 + test/jdk/tools/jpackage/share/ErrorTest.java | 4 +- .../jpackage/share/RuntimePackageTest.java | 9 +- 14 files changed, 582 insertions(+), 211 deletions(-) create mode 100644 src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/ActiveKeychainList.java delete mode 100644 src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageInfoPListFile.java delete mode 100644 src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java create mode 100644 test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/ActiveKeychainListTest.java diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/ActiveKeychainList.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/ActiveKeychainList.java new file mode 100644 index 00000000000..ab41fc0a60e --- /dev/null +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/ActiveKeychainList.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jpackage.internal; + +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import jdk.internal.util.OSVersion; + +final class ActiveKeychainList implements Closeable { + + static Optional createForPlatform(List keychains) throws IOException { + if (!keychains.isEmpty() && Globals.instance().findBooleanProperty(ActiveKeychainList.class).orElseGet(ActiveKeychainList::isRequired)) { + return Optional.of(new ActiveKeychainList(keychains)); + } else { + return Optional.empty(); + } + } + + static Optional createForPlatform(Keychain... keychains) throws IOException { + return createForPlatform(List.of(keychains)); + } + + @SuppressWarnings("try") + static void withKeychains(Consumer> keychainConsumer, List keychains) throws IOException { + var keychainList = createForPlatform(keychains); + if (keychainList.isEmpty()) { + keychainConsumer.accept(keychains); + } else { + try (var kl = keychainList.get()) { + keychainConsumer.accept(keychains); + } + } + } + + static void withKeychain(Consumer keychainConsumer, Keychain keychain) throws IOException { + + Objects.requireNonNull(keychainConsumer); + withKeychains(keychains -> { + keychainConsumer.accept(keychains.getFirst()); + }, List.of(keychain)); + } + + ActiveKeychainList(List requestedKeychains, List currentKeychains, boolean force) throws IOException { + this.requestedKeychains = List.copyOf(requestedKeychains); + this.oldKeychains = List.copyOf(currentKeychains); + + final List cmdline = new ArrayList<>(LIST_KEYCHAINS_CMD_PREFIX); + addKeychains(cmdline, oldKeychains); + + if (force) { + this.currentKeychains = requestedKeychains; + restoreKeychainsCmd = List.copyOf(cmdline); + cmdline.subList(LIST_KEYCHAINS_CMD_PREFIX.size(), cmdline.size()).clear(); + addKeychains(cmdline, requestedKeychains); + } else { + final var currentKeychainPaths = oldKeychains.stream().map(Keychain::path).toList(); + + final var missingKeychains = requestedKeychains.stream().filter(k -> { + return !currentKeychainPaths.contains(k.path()); + }).toList(); + + if (missingKeychains.isEmpty()) { + this.currentKeychains = oldKeychains; + restoreKeychainsCmd = List.of(); + } else { + this.currentKeychains = Stream.of(oldKeychains, missingKeychains) + .flatMap(List::stream).collect(Collectors.toUnmodifiableList()); + restoreKeychainsCmd = List.copyOf(cmdline); + addKeychains(cmdline, missingKeychains); + } + } + + Executor.of(cmdline).executeExpectSuccess(); + } + + ActiveKeychainList(List keychains) throws IOException { + this(keychains, Keychain.listKeychains(), false); + } + + List requestedKeychains() { + return requestedKeychains; + } + + List currentKeychains() { + return currentKeychains; + } + + List restoreKeychains() { + return oldKeychains; + } + + @Override + public void close() throws IOException { + if (!restoreKeychainsCmd.isEmpty()) { + Executor.of(restoreKeychainsCmd).executeExpectSuccess(); + } + } + + private static void addKeychains(List cmdline, List keychains) { + cmdline.addAll(keychains.stream().map(Keychain::asCliArg).toList()); + } + + private static boolean isRequired() { + // Required for OS X 10.12+ + return 0 <= OSVersion.current().compareTo(new OSVersion(10, 12)); + } + + private final List requestedKeychains; + private final List currentKeychains; + private final List oldKeychains; + private final List restoreKeychainsCmd; + + private final static List LIST_KEYCHAINS_CMD_PREFIX = List.of("/usr/bin/security", "list-keychains", "-s"); +} diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageInfoPListFile.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageInfoPListFile.java deleted file mode 100644 index 602e147a970..00000000000 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageInfoPListFile.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.jpackage.internal; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import jdk.jpackage.internal.model.DottedVersion; -import jdk.jpackage.internal.util.PListReader; -import org.xml.sax.SAXException; - -/** - * Mandatory elements of Info.plist file of app image. - */ -record AppImageInfoPListFile(String bundleIdentifier, String bundleName, String copyright, - DottedVersion shortVersion, DottedVersion bundleVersion, String category) { - - static final class InvalidPlistFileException extends Exception { - InvalidPlistFileException(Throwable cause) { - super(cause); - } - - private static final long serialVersionUID = 1L; - } - - static AppImageInfoPListFile loadFromInfoPList(Path infoPListFile) - throws IOException, InvalidPlistFileException, SAXException { - - final var plistReader = new PListReader(Files.readAllBytes(infoPListFile)); - - try { - return new AppImageInfoPListFile( - plistReader.queryValue("CFBundleIdentifier"), - plistReader.queryValue("CFBundleName"), - plistReader.queryValue("NSHumanReadableCopyright"), - DottedVersion.greedy(plistReader.queryValue("CFBundleShortVersionString")), - DottedVersion.greedy(plistReader.queryValue("CFBundleVersion")), - plistReader.queryValue("LSApplicationCategoryType")); - } catch (Exception ex) { - throw new InvalidPlistFileException(ex); - } - } -} diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java index 43590fb5e2c..cdccd488ed6 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java @@ -36,20 +36,24 @@ import java.util.stream.Stream; import jdk.jpackage.internal.model.AppImageLayout; import jdk.jpackage.internal.model.AppImageSigningConfig; import jdk.jpackage.internal.model.Application; +import jdk.jpackage.internal.model.ApplicationLaunchers; +import jdk.jpackage.internal.model.ExternalApplication; +import jdk.jpackage.internal.model.JPackageException; import jdk.jpackage.internal.model.Launcher; import jdk.jpackage.internal.model.MacApplication; import jdk.jpackage.internal.model.MacApplicationMixin; -import jdk.jpackage.internal.model.JPackageException; +import jdk.jpackage.internal.util.PListReader; +import jdk.jpackage.internal.util.Result; import jdk.jpackage.internal.util.RootedPath; final class MacApplicationBuilder { - MacApplicationBuilder(Application app) { - this.app = Objects.requireNonNull(app); + MacApplicationBuilder(ApplicationBuilder appBuilder) { + this.superBuilder = Objects.requireNonNull(appBuilder); } private MacApplicationBuilder(MacApplicationBuilder other) { - this(other.app); + this(other.superBuilder.copy()); icon = other.icon; bundleName = other.bundleName; bundleIdentifier = other.bundleIdentifier; @@ -94,18 +98,28 @@ final class MacApplicationBuilder { return this; } + Optional externalApplication() { + return superBuilder.externalApplication(); + } + + Optional launchers() { + return superBuilder.launchers(); + } + MacApplication create() { if (externalInfoPlistFile != null) { return createCopyForExternalInfoPlistFile().create(); } + var app = superBuilder.create(); + validateAppVersion(app); validateAppContentDirs(app); final var mixin = new MacApplicationMixin.Stub( validatedIcon(), - validatedBundleName(), - validatedBundleIdentifier(), + validatedBundleName(app), + validatedBundleIdentifier(app), validatedCategory(), appStore, createSigningConfig()); @@ -161,39 +175,58 @@ final class MacApplicationBuilder { } private MacApplicationBuilder createCopyForExternalInfoPlistFile() { - try { - final var plistFile = AppImageInfoPListFile.loadFromInfoPList(externalInfoPlistFile); + final var builder = new MacApplicationBuilder(this); - final var builder = new MacApplicationBuilder(this); + builder.externalInfoPlistFile(null); - builder.externalInfoPlistFile(null); + Result plistResult = Result.of(() -> { + return new PListReader(Files.readAllBytes(externalInfoPlistFile)); + }, Exception.class); + plistResult.value().ifPresent(plist -> { if (builder.bundleName == null) { - builder.bundleName(plistFile.bundleName()); + plist.findValue("CFBundleName").ifPresent(builder::bundleName); } if (builder.bundleIdentifier == null) { - builder.bundleIdentifier(plistFile.bundleIdentifier()); + plist.findValue("CFBundleIdentifier").ifPresent(builder::bundleIdentifier); } if (builder.category == null) { - builder.category(plistFile.category()); + plist.findValue("LSApplicationCategoryType").ifPresent(builder::category); } - return builder; - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } catch (Exception ex) { - throw new JPackageException( - I18N.format("error.invalid-app-image-plist-file", externalInfoPlistFile), ex); - } + if (builder.superBuilder.version().isEmpty()) { + plist.findValue("CFBundleVersion").ifPresent(builder.superBuilder::version); + } + }); + + plistResult.firstError().filter(_ -> { + // If we are building a runtime and the Info.plist file of the predefined + // runtime bundle is malformed or unavailable, ignore it. + return !superBuilder.isRuntime(); + }).ifPresent(ex -> { + // We are building an application from the predefined app image and + // the Info.plist file in the predefined app image bundle is malformed or unavailable. Bail out. + switch (ex) { + case IOException ioex -> { + throw new UncheckedIOException(ioex); + } + default -> { + throw new JPackageException( + I18N.format("error.invalid-app-image-plist-file", externalInfoPlistFile), ex); + } + } + }); + + return builder; } private Optional createSigningConfig() { return Optional.ofNullable(signingBuilder).map(AppImageSigningConfigBuilder::create); } - private String validatedBundleName() { + private String validatedBundleName(Application app) { final var value = Optional.ofNullable(bundleName).orElseGet(() -> { final var appName = app.name(); // Commented out for backward compatibility @@ -212,7 +245,7 @@ final class MacApplicationBuilder { return value; } - private String validatedBundleIdentifier() { + private String validatedBundleIdentifier(Application app) { final var value = Optional.ofNullable(bundleIdentifier).orElseGet(() -> { return app.mainLauncher() .flatMap(Launcher::startupInfo) @@ -255,7 +288,7 @@ final class MacApplicationBuilder { private Path externalInfoPlistFile; private AppImageSigningConfigBuilder signingBuilder; - private final Application app; + private final ApplicationBuilder superBuilder; private static final Defaults DEFAULTS = new Defaults("utilities"); diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java index 4cd4f386ad8..be9519c57a6 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java @@ -198,7 +198,7 @@ final class MacFromOptions { } } - private static ApplicationWithDetails createMacApplicationInternal(Options options) { + private static ApplicationBuilder createApplicationBuilder(Options options) { final var predefinedRuntimeLayout = PREDEFINED_RUNTIME_IMAGE.findIn(options) .map(MacPackage::guessRuntimeLayout); @@ -236,12 +236,30 @@ final class MacFromOptions { final var app = superAppBuilder.create(); - final var appBuilder = new MacApplicationBuilder(app); + return superAppBuilder; + } - PREDEFINED_APP_IMAGE.findIn(options) - .map(MacBundle::new) - .map(MacBundle::infoPlistFile) - .ifPresent(appBuilder::externalInfoPlistFile); + private static ApplicationWithDetails createMacApplicationInternal(Options options) { + + final var appBuilder = new MacApplicationBuilder(createApplicationBuilder(options)); + + if (OptionUtils.isRuntimeInstaller(options)) { + // Predefined runtime image, if specified, can be a macOS bundle or regular directory. + // Notify application builder with the path to the plist file in the predefined runtime image only if the file exists. + // If it doesn't, jpackage should keep going. + PREDEFINED_RUNTIME_IMAGE.findIn(options) + .flatMap(MacBundle::fromPath) + .map(MacBundle::infoPlistFile) + .ifPresent(appBuilder::externalInfoPlistFile); + } else { + // Predefined app image, if specified, should always be a valid macOS bundle. + // Notify application builder with the path to the plist file in the predefined app image without checking if the file exists. + // If it doesn't, the builder should throw and jpackage should exit with error. + PREDEFINED_APP_IMAGE.findIn(options) + .map(MacBundle::new) + .map(MacBundle::infoPlistFile) + .ifPresent(appBuilder::externalInfoPlistFile); + } ICON.ifPresentIn(options, appBuilder::icon); MAC_BUNDLE_NAME.ifPresentIn(options, appBuilder::bundleName); @@ -252,7 +270,7 @@ final class MacFromOptions { final boolean appStore; if (PREDEFINED_APP_IMAGE.containsIn(options)) { - final var appImageFileOptions = superAppBuilder.externalApplication().orElseThrow().extra(); + final var appImageFileOptions = appBuilder.externalApplication().orElseThrow().extra(); appStore = MAC_APP_STORE.getFrom(appImageFileOptions); } else { appStore = MAC_APP_STORE.getFrom(options); @@ -295,7 +313,7 @@ final class MacFromOptions { signingBuilder.entitlementsResourceName("sandbox.plist"); } - app.mainLauncher().flatMap(Launcher::startupInfo).ifPresentOrElse( + appBuilder.launchers().map(ApplicationLaunchers::mainLauncher).flatMap(Launcher::startupInfo).ifPresentOrElse( signingBuilder::signingIdentifierPrefix, () -> { // Runtime installer does not have the main launcher, use @@ -310,7 +328,7 @@ final class MacFromOptions { appBuilder.signingBuilder(signingBuilder); } - return new ApplicationWithDetails(appBuilder.create(), superAppBuilder.externalApplication()); + return new ApplicationWithDetails(appBuilder.create(), appBuilder.externalApplication()); } private static MacPackageBuilder createMacPackageBuilder(Options options, ApplicationWithDetails app, PackageType type) { diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java index 4e63f6db178..d75b7d0b9cd 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackagingPipeline.java @@ -500,7 +500,7 @@ final class MacPackagingPipeline { }; app.signingConfig().flatMap(AppImageSigningConfig::keychain).map(Keychain::new).ifPresentOrElse(keychain -> { - toBiConsumer(TempKeychain::withKeychain).accept(unused -> signAction.run(), keychain); + toBiConsumer(ActiveKeychainList::withKeychain).accept(unused -> signAction.run(), keychain); }, signAction); } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java deleted file mode 100644 index 2f616aafba1..00000000000 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jpackage.internal; - -import java.io.Closeable; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; -import jdk.internal.util.OSVersion; - -final class TempKeychain implements Closeable { - - static void withKeychains(Consumer> keychainConsumer, List keychains) { - - keychains.forEach(Objects::requireNonNull); - if (keychains.isEmpty() || OSVersion.current().compareTo(new OSVersion(10, 12)) < 0) { - keychainConsumer.accept(keychains); - } else { - // we need this for OS X 10.12+ - try (var tempKeychain = new TempKeychain(keychains)) { - keychainConsumer.accept(tempKeychain.keychains); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - } - } - - static void withKeychain(Consumer keychainConsumer, Keychain keychain) { - - Objects.requireNonNull(keychainConsumer); - withKeychains(keychains -> { - keychainConsumer.accept(keychains.getFirst()); - }, List.of(keychain)); - } - - TempKeychain(List keychains) throws IOException { - this.keychains = Objects.requireNonNull(keychains); - - final var currentKeychains = Keychain.listKeychains(); - - final var currentKeychainPaths = currentKeychains.stream().map(Keychain::path).toList(); - - final var missingKeychains = keychains.stream().filter(k -> { - return !currentKeychainPaths.contains(k.path()); - }).toList(); - - if (missingKeychains.isEmpty()) { - restoreKeychainsCmd = List.of(); - } else { - List args = new ArrayList<>(); - args.add("/usr/bin/security"); - args.add("list-keychains"); - args.add("-s"); - args.addAll(currentKeychains.stream().map(Keychain::asCliArg).toList()); - - restoreKeychainsCmd = List.copyOf(args); - - args.addAll(missingKeychains.stream().map(Keychain::asCliArg).toList()); - - Executor.of(args).executeExpectSuccess(); - } - } - - List keychains() { - return keychains; - } - - @Override - public void close() throws IOException { - if (!restoreKeychainsCmd.isEmpty()) { - Executor.of(restoreKeychainsCmd).executeExpectSuccess(); - } - } - - private final List keychains; - private final List restoreKeychainsCmd; -} diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java index 9d5407524a8..ebfae9f8d4c 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java @@ -45,10 +45,32 @@ import jdk.jpackage.internal.model.LauncherIcon; import jdk.jpackage.internal.model.LauncherStartupInfo; import jdk.jpackage.internal.model.ResourceDirLauncherIcon; import jdk.jpackage.internal.model.RuntimeBuilder; +import jdk.jpackage.internal.model.RuntimeLayout; import jdk.jpackage.internal.util.RootedPath; final class ApplicationBuilder { + ApplicationBuilder() { + } + + ApplicationBuilder(ApplicationBuilder other) { + name = other.name; + description = other.description; + version = other.version; + vendor = other.vendor; + copyright = other.copyright; + appDirSources = other.appDirSources; + externalApp = other.externalApp; + contentDirSources = other.contentDirSources; + appImageLayout = other.appImageLayout; + runtimeBuilder = other.runtimeBuilder; + launchers = other.launchers; + } + + ApplicationBuilder copy() { + return new ApplicationBuilder(this); + } + Application create() { Objects.requireNonNull(appImageLayout); @@ -103,6 +125,11 @@ final class ApplicationBuilder { return this; } + boolean isRuntime() { + return Optional.ofNullable(appImageLayout) + .orElseThrow(IllegalStateException::new) instanceof RuntimeLayout; + } + ApplicationBuilder name(String v) { name = v; return this; @@ -118,6 +145,10 @@ final class ApplicationBuilder { return this; } + Optional version() { + return Optional.ofNullable(version); + } + ApplicationBuilder vendor(String v) { vendor = v; return this; diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java index d5c714d1a47..0128d050c25 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Globals.java @@ -25,6 +25,9 @@ package jdk.jpackage.internal; import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; @@ -47,6 +50,21 @@ public final class Globals { return objectFactory(ObjectFactory.build(objectFactory).executorFactory(v).create()); } + @SuppressWarnings("unchecked") + public Optional findProperty(Object key) { + return Optional.ofNullable((T)properties.get(Objects.requireNonNull(key))); + } + + public Optional findBooleanProperty(Object key) { + return findProperty(key); + } + + public Globals setProperty(Object key, T value) { + checkMutable(); + properties.compute(Objects.requireNonNull(key), (_, _) -> value); + return this; + } + Log.Logger logger() { return logger; } @@ -79,6 +97,7 @@ public final class Globals { private ObjectFactory objectFactory = ObjectFactory.DEFAULT; private final Log.Logger logger = new Log.Logger(); + private final Map properties = new HashMap<>(); private static final ScopedValue INSTANCE = ScopedValue.newInstance(); private static final Globals DEFAULT = new Globals(); 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 2e58ea7a0ab..f68ac90d284 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -60,6 +60,7 @@ import java.util.spi.ToolProvider; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import jdk.jpackage.internal.util.MacBundle; import jdk.jpackage.internal.util.function.ExceptionBox; import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.internal.util.function.ThrowingFunction; @@ -245,7 +246,18 @@ public class JPackageCommand extends CommandArguments { public String version() { return PropertyFinder.findAppProperty(this, - PropertyFinder.cmdlineOptionWithValue("--app-version"), + PropertyFinder.cmdlineOptionWithValue("--app-version").or(cmd -> { + if (cmd.isRuntime() && PackageType.MAC.contains(cmd.packageType())) { + // This is a macOS runtime bundle. + var predefinedRuntimeBundle = MacBundle.fromPath(Path.of(cmd.getArgumentValue("--runtime-image"))); + if (predefinedRuntimeBundle.isPresent()) { + // This is a macOS runtime bundle created from the predefined runtime bundle (not a predefined runtime directory). + // The version of this bundle should be copied from the Info.plist file of the predefined runtime bundle. + return MacHelper.readPList(predefinedRuntimeBundle.get().infoPlistFile()).findValue("CFBundleVersion"); + } + } + return Optional.empty(); + }), PropertyFinder.appImageFile(appImageFile -> { return appImageFile.version(); }) diff --git a/test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/ActiveKeychainListTest.java b/test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/ActiveKeychainListTest.java new file mode 100644 index 00000000000..2ff5317e60d --- /dev/null +++ b/test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/ActiveKeychainListTest.java @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jpackage.internal; + +import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; +import jdk.jpackage.test.mock.CommandAction; +import jdk.jpackage.test.mock.CommandActionSpec; +import jdk.jpackage.test.mock.CommandActionSpecs; +import jdk.jpackage.test.mock.CommandMockSpec; +import jdk.jpackage.test.mock.MockIllegalStateException; +import jdk.jpackage.test.mock.Script; +import jdk.jpackage.test.stdmock.JPackageMockUtils; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class ActiveKeychainListTest { + + @ParameterizedTest + @CsvSource(value = { + "'','',''", + "a,'',a", + "'',a,a", + "a,a,a", + "abc,b,abc", + "abc,ba,abc", + "abc,bad,abcd", + "ac,b,acb" + }) + void test_ctor_and_createForPlatform(String initial, String requested, String current) throws IOException { + + var initialKeychains = parseKeychainList(initial); + var requestedKeychains = parseKeychainList(requested); + + var securityMock = new SecurityKeychainListMock(true); + initialKeychains.stream().map(Keychain::name).forEach(securityMock.keychainNames()::add); + + Globals.main(toSupplier(() -> { + securityMock.applyToGlobals(); + Globals.instance().setProperty(ActiveKeychainList.class, false); + + assertTrue(ActiveKeychainList.createForPlatform(requestedKeychains.toArray(Keychain[]::new)).isEmpty()); + + var akl = new ActiveKeychainList(List.copyOf(requestedKeychains)); + try (akl) { + assertEquals(initialKeychains, akl.restoreKeychains()); + assertEquals(requestedKeychains, akl.requestedKeychains()); + assertEquals(parseKeychainList(current), akl.currentKeychains()); + assertEquals(akl.currentKeychains(), securityMock.keychains()); + } + + assertEquals(initialKeychains, akl.restoreKeychains()); + assertEquals(requestedKeychains, akl.requestedKeychains()); + assertEquals(parseKeychainList(current), akl.currentKeychains()); + assertEquals(initialKeychains, securityMock.keychains()); + + return 0; + })); + } + + @ParameterizedTest + @CsvSource(value = { + "'','','',true", + "'','','',false", + + "a,'','',true", + "a,'',a,false", + + "'',a,a,true", + "'',a,a,false", + + "a,a,a,true", + "a,a,a,false", + + "abc,b,b,true", + "abc,b,abc,false", + + "abc,ba,ba,true", + "abc,ba,abc,false", + + "abc,bad,bad,true", + "abc,bad,abcd,false", + + "ac,b,b,true", + "ac,b,acb,false" + }) + void testCtorWithForced(String initial, String requested, String current, boolean forced) throws IOException { + + var initialKeychains = parseKeychainList(initial); + var requestedKeychains = parseKeychainList(requested); + + var securityMock = new SecurityKeychainListMock(forced); + securityMock.keychainNames().addAll(List.of("foo", "bar")); + + Globals.main(toSupplier(() -> { + securityMock.applyToGlobals(); + + var akl = new ActiveKeychainList(List.copyOf(requestedKeychains), List.copyOf(initialKeychains), forced); + try (akl) { + assertEquals(initialKeychains, akl.restoreKeychains()); + assertEquals(requestedKeychains, akl.requestedKeychains()); + assertEquals(parseKeychainList(current), akl.currentKeychains()); + assertEquals(akl.currentKeychains(), securityMock.keychains()); + } + + assertEquals(initialKeychains, akl.restoreKeychains()); + assertEquals(requestedKeychains, akl.requestedKeychains()); + assertEquals(parseKeychainList(current), akl.currentKeychains()); + assertEquals(initialKeychains, securityMock.keychains()); + + return 0; + })); + } + + @ParameterizedTest + @CsvSource(value = { + "'','',", + "a,'',", + "'',a,a", + "a,a,a", + "abc,b,abc", + "abc,ba,abc", + "abc,bad,abcd", + "ac,b,acb" + }) + void test_withKeychain(String initial, String requested, String current) throws IOException { + + var initialKeychains = parseKeychainList(initial); + var requestedKeychains = parseKeychainList(requested); + + for (boolean isRequired : List.of(true, false)) { + var securityMock = new SecurityKeychainListMock(true); + initialKeychains.stream().map(Keychain::name).forEach(securityMock.keychainNames()::add); + + Consumer> workload = keychains -> { + assertEquals(requestedKeychains, keychains); + if (isRequired && current != null) { + assertEquals(parseKeychainList(current), securityMock.keychains()); + } else { + assertEquals(initialKeychains, securityMock.keychains()); + } + }; + + Globals.main(toSupplier(() -> { + Globals.instance().setProperty(ActiveKeychainList.class, isRequired); + + securityMock.applyToGlobals(); + ActiveKeychainList.withKeychains(workload, requestedKeychains); + + assertEquals(initialKeychains, securityMock.keychains()); + + if (requestedKeychains.size() == 1) { + securityMock.applyToGlobals(); + ActiveKeychainList.withKeychain(keychain -> { + workload.accept(List.of(keychain)); + }, requestedKeychains.getFirst()); + + assertEquals(initialKeychains, securityMock.keychains()); + } + + return 0; + })); + } + } + + /** + * Mocks "/usr/bin/security list-keychain" command. + */ + record SecurityKeychainListMock(List keychainNames, boolean isReadAllowed) implements CommandAction { + + SecurityKeychainListMock { + Objects.requireNonNull(keychainNames); + } + + SecurityKeychainListMock(boolean isReadAllowed) { + this(new ArrayList<>(), isReadAllowed); + } + + List keychains() { + return keychainNames.stream().map(Keychain::new).toList(); + } + + void applyToGlobals() { + CommandActionSpec actionSpec = CommandActionSpec.create("/usr/bin/security", this); + + var script = Script.build() + .commandMockBuilderMutator(mockBuilder -> { + // Limit the number of times the mock can be executed. + // It should be one or twice. + // Once, when ActiveKeychainList is constructed such that it doesn't read + // the current active keychain list from the "/usr/bin/security" command, but takes it from the parameter. + // Twice, when ActiveKeychainList is constructed such that it read + // the current active keychain list from the "/usr/bin/security" command. + mockBuilder.repeat(isReadAllowed ? 2 : 1); + }) + // Replace "/usr/bin/security" with the mock bound to the keychain mock. + .map(new CommandMockSpec(actionSpec.description(), "security-list-keychain", CommandActionSpecs.build().action(actionSpec).create())) + .createLoop(); + + JPackageMockUtils.buildJPackage() + .script(script) + .listener(System.out::println) + .applyToGlobals(); + } + + @Override + public Optional run(Context context) throws Exception, MockIllegalStateException { + final var origContext = context; + + if (!context.args().getFirst().equals("list-keychains")) { + throw origContext.unexpectedArguments(); + } + + context = context.shift(); + + if (context.args().isEmpty()) { + if (isReadAllowed) { + keychainNames.stream().map(k -> { + return new StringBuilder().append('"').append(k).append('"').toString(); + }).forEach(context::printlnOut); + } else { + throw origContext.unexpectedArguments(); + } + } else if (context.args().getFirst().equals("-s")) { + keychainNames.clear(); + keychainNames.addAll(context.shift().args()); + } else { + throw origContext.unexpectedArguments(); + } + + return Optional.of(0); + } + } + + private static List parseKeychainList(String str) { + return str.chars().mapToObj(chr -> { + return new StringBuilder().append((char)chr).toString(); + }).map(Keychain::new).toList(); + } +} diff --git a/test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/MacDmgPackagerTest.java b/test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/MacDmgPackagerTest.java index 0e4893c8a06..3b71d53e2db 100644 --- a/test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/MacDmgPackagerTest.java +++ b/test/jdk/tools/jpackage/junit/macosx/jdk.jpackage/jdk/jpackage/internal/MacDmgPackagerTest.java @@ -175,13 +175,12 @@ public class MacDmgPackagerTest { private static void runPackagingMock(Path workDir, MacDmgSystemEnvironment sysEnv) { - var app = new ApplicationBuilder() + var appBuilder = new ApplicationBuilder() .appImageLayout(MacPackagingPipeline.APPLICATION_LAYOUT) .runtimeBuilder(createRuntimeBuilder()) - .name("foo") - .create(); + .name("foo"); - var macApp = new MacApplicationBuilder(app).create(); + var macApp = new MacApplicationBuilder(appBuilder).create(); var macDmgPkg = new MacDmgPackageBuilder(new MacPackageBuilder(new PackageBuilder(macApp, MAC_DMG))).create(); diff --git a/test/jdk/tools/jpackage/junit/macosx/junit.java b/test/jdk/tools/jpackage/junit/macosx/junit.java index 2253211add0..4ab05daf1ae 100644 --- a/test/jdk/tools/jpackage/junit/macosx/junit.java +++ b/test/jdk/tools/jpackage/junit/macosx/junit.java @@ -52,3 +52,14 @@ * jdk/jpackage/internal/MacDmgPackagerTest.java * @run junit jdk.jpackage/jdk.jpackage.internal.MacDmgPackagerTest */ + +/* @test + * @summary Test ActiveKeychainListTest + * @requires (os.family == "mac") + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.mock.* + * @build jdk.jpackage.test.stdmock.* + * @compile/module=jdk.jpackage -Xlint:all -Werror + * jdk/jpackage/internal/ActiveKeychainListTest.java + * @run junit jdk.jpackage/jdk.jpackage.internal.ActiveKeychainListTest + */ diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index b325c02f039..db87263884b 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -140,11 +140,9 @@ public final class ErrorTest { var appImageDir = (Path)APP_IMAGE.expand(cmd).orElseThrow(); // Replace the default Info.plist file with an empty one. var plistFile = new MacBundle(appImageDir).infoPlistFile(); - TKit.trace(String.format("Create invalid plist file in [%s]", plistFile)); + TKit.trace(String.format("Create invalid plist file [%s]", plistFile)); createXml(plistFile, xml -> { writePList(xml, toXmlConsumer(() -> { - writeDict(xml, toXmlConsumer(() -> { - })); })); }); return appImageDir; diff --git a/test/jdk/tools/jpackage/share/RuntimePackageTest.java b/test/jdk/tools/jpackage/share/RuntimePackageTest.java index 6cc668f94f9..a18efce62c6 100644 --- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,12 @@ public class RuntimePackageTest { @Test(ifOS = MACOS) public static void testFromBundle() { - init(MacHelper::createRuntimeBundle).run(); + init(() -> { + return MacHelper.buildRuntimeBundle().mutator(cmd -> { + // Set custom version in the Info.plist file of the predefined runtime bundle. + cmd.addArguments("--app-version", "17.52"); + }).create(); + }).run(); } @Test(ifOS = LINUX) From 6808ba2e05b8dba6c28ee21d4c415a81a950f5c1 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Tue, 10 Mar 2026 00:21:47 +0000 Subject: [PATCH 134/170] 8378293: GenShen: Simplify selection of aged regions Reviewed-by: kdnilsen, ysr --- .../shenandoahGenerationalHeuristics.cpp | 170 ++++++------------ .../shenandoahGenerationalHeuristics.hpp | 11 +- .../heuristics/shenandoahGlobalHeuristics.cpp | 2 +- .../heuristics/shenandoahHeuristics.cpp | 33 ++-- .../heuristics/shenandoahHeuristics.hpp | 2 + .../heuristics/shenandoahYoungHeuristics.cpp | 20 +-- .../heuristics/shenandoahYoungHeuristics.hpp | 3 +- .../gc/shenandoah/shenandoahCollectionSet.cpp | 1 - .../gc/shenandoah/shenandoahCollectionSet.hpp | 22 --- .../shenandoahCollectionSetPreselector.hpp | 51 ------ .../shenandoah/shenandoahInPlacePromoter.cpp | 43 ++--- .../shenandoah/shenandoahInPlacePromoter.hpp | 67 ++++++- 12 files changed, 160 insertions(+), 265 deletions(-) delete mode 100644 src/hotspot/share/gc/shenandoah/shenandoahCollectionSetPreselector.hpp diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index f3d31b8d0e1..4b665501d71 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -25,7 +25,6 @@ #include "gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" -#include "gc/shenandoah/shenandoahCollectionSetPreselector.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" @@ -76,20 +75,19 @@ ShenandoahGenerationalHeuristics::ShenandoahGenerationalHeuristics(ShenandoahGen } void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set) { - ShenandoahHeap* heap = ShenandoahHeap::heap(); + ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); + + assert(collection_set->is_empty(), "Collection set must be empty here"); _add_regions_to_old = 0; - - // Seed the collection set with resource area-allocated - // preselected regions, which are removed when we exit this scope. - ShenandoahCollectionSetPreselector preselector(collection_set, heap->num_regions()); + ShenandoahInPlacePromotionPlanner in_place_promotions(heap); // Find the amount that will be promoted, regions that will be promoted in // place, and preselected older regions that will be promoted by evacuation. - compute_evacuation_budgets(heap); + compute_evacuation_budgets(in_place_promotions, heap); // Choose the collection set, including the regions preselected above for promotion into the old generation. - filter_regions(collection_set); + filter_regions(in_place_promotions, collection_set); // Even if collection_set->is_empty(), we want to adjust budgets, making reserves available to mutator. adjust_evacuation_budgets(heap, collection_set); @@ -108,7 +106,8 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio } } -void ShenandoahGenerationalHeuristics::compute_evacuation_budgets(ShenandoahHeap* const heap) { +void ShenandoahGenerationalHeuristics::compute_evacuation_budgets(ShenandoahInPlacePromotionPlanner& in_place_promotions, + ShenandoahHeap* const heap) { shenandoah_assert_generational(); ShenandoahOldGeneration* const old_generation = heap->old_generation(); @@ -206,7 +205,7 @@ void ShenandoahGenerationalHeuristics::compute_evacuation_budgets(ShenandoahHeap // If is_global(), we let garbage-first heuristic determine cset membership. Otherwise, we give priority // to tenurable regions by preselecting regions for promotion by evacuation (obtaining the live data to seed promoted_reserve). // This also identifies regions that will be promoted in place. These use the tenuring threshold. - const size_t consumed_by_advance_promotion = select_aged_regions(_generation->is_global()? 0: old_promo_reserve); + const size_t consumed_by_advance_promotion = select_aged_regions(in_place_promotions, _generation->is_global()? 0: old_promo_reserve); assert(consumed_by_advance_promotion <= old_promo_reserve, "Do not promote more than budgeted"); // The young evacuation reserve can be no larger than young_unaffiliated. Planning to evacuate into partially consumed @@ -230,24 +229,21 @@ void ShenandoahGenerationalHeuristics::compute_evacuation_budgets(ShenandoahHeap // case of a GLOBAL gc. During choose_collection_set() of GLOBAL, old will be expanded on demand. } -void ShenandoahGenerationalHeuristics::filter_regions(ShenandoahCollectionSet* collection_set) { - assert(collection_set->is_empty(), "Must be empty"); - +void ShenandoahGenerationalHeuristics::filter_regions(ShenandoahInPlacePromotionPlanner& in_place_promotions, + ShenandoahCollectionSet* collection_set) { auto heap = ShenandoahGenerationalHeap::heap(); - size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes(); - + const size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes(); // Check all pinned regions have updated status before choosing the collection set. heap->assert_pinned_region_status(_generation); // Step 1. Build up the region candidates we care about, rejecting losers and accepting winners right away. - size_t num_regions = heap->num_regions(); + const size_t num_regions = heap->num_regions(); RegionData* candidates = _region_data; size_t cand_idx = 0; - size_t preselected_candidates = 0; size_t total_garbage = 0; @@ -257,23 +253,12 @@ void ShenandoahGenerationalHeuristics::filter_regions(ShenandoahCollectionSet* c size_t free = 0; size_t free_regions = 0; - // This counts number of humongous regions that we intend to promote in this cycle. - size_t humongous_regions_promoted = 0; - // This counts number of regular regions that will be promoted in place. - size_t regular_regions_promoted_in_place = 0; - // This counts bytes of memory used by regular regions to be promoted in place. - size_t regular_regions_promoted_usage = 0; - // This counts bytes of memory free in regular regions to be promoted in place. - size_t regular_regions_promoted_free = 0; - // This counts bytes of garbage memory in regular regions to be promoted in place. - size_t regular_regions_promoted_garbage = 0; - for (size_t i = 0; i < num_regions; i++) { ShenandoahHeapRegion* region = heap->get_region(i); if (!_generation->contains(region)) { continue; } - size_t garbage = region->garbage(); + const size_t garbage = region->garbage(); total_garbage += garbage; if (region->is_empty()) { free_regions++; @@ -285,85 +270,48 @@ void ShenandoahGenerationalHeuristics::filter_regions(ShenandoahCollectionSet* c immediate_garbage += garbage; region->make_trash_immediate(); } else { - bool is_candidate; - // This is our candidate for later consideration. - if (collection_set->is_preselected(i)) { - assert(heap->is_tenurable(region), "Preselection filter"); - is_candidate = true; - preselected_candidates++; - // Set garbage value to maximum value to force this into the sorted collection set. - garbage = region_size_bytes; + if (collection_set->is_in(i)) { + assert(heap->is_tenurable(region), "Preselected region %zu must be tenurable", i); } else if (region->is_young() && heap->is_tenurable(region)) { // Note that for GLOBAL GC, region may be OLD, and OLD regions do not qualify for pre-selection - // This region is old enough to be promoted but it was not preselected, either because its garbage is below - // old garbage threshold so it will be promoted in place, or because there is not sufficient room - // in old gen to hold the evacuated copies of this region's live data. In both cases, we choose not to + // This region is old enough to be promoted, but it was not preselected, either because its garbage is below + // old garbage threshold so it will be promoted in place, or because there is insufficient room + // in old gen to hold the evacuated copies of this region's live data. In either case, we choose not to // place this region into the collection set. - if (region->get_top_before_promote() != nullptr) { - // Region was included for promotion-in-place - regular_regions_promoted_in_place++; - regular_regions_promoted_usage += region->used_before_promote(); - regular_regions_promoted_free += region->free(); - regular_regions_promoted_garbage += region->garbage(); - } - is_candidate = false; } else { - is_candidate = true; - } - if (is_candidate) { + // This is our candidate for later consideration. + assert(region->get_top_before_promote() == nullptr, "Cannot add region %zu scheduled for in-place-promotion to the collection set", i); candidates[cand_idx].set_region_and_garbage(region, garbage); cand_idx++; } } } else if (region->is_humongous_start()) { // Reclaim humongous regions here, and count them as the immediate garbage -#ifdef ASSERT - bool reg_live = region->has_live(); - bool bm_live = _generation->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); - assert(reg_live == bm_live, - "Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu", - BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words()); -#endif + DEBUG_ONLY(assert_humongous_mark_consistency(region)); if (!region->has_live()) { heap->trash_humongous_region_at(region); // Count only the start. Continuations would be counted on "trash" path immediate_regions++; immediate_garbage += garbage; - } else { - if (region->is_young() && heap->is_tenurable(region)) { - oop obj = cast_to_oop(region->bottom()); - size_t humongous_regions = ShenandoahHeapRegion::required_regions(obj->size() * HeapWordSize); - humongous_regions_promoted += humongous_regions; - } } } else if (region->is_trash()) { - // Count in just trashed collection set, during coalesced CM-with-UR + // Count in just trashed humongous continuation regions immediate_regions++; immediate_garbage += garbage; } } - heap->old_generation()->set_expected_humongous_region_promotions(humongous_regions_promoted); - heap->old_generation()->set_expected_regular_region_promotions(regular_regions_promoted_in_place); - log_info(gc, ergo)("Planning to promote in place %zu humongous regions and %zu" - " regular regions, spanning a total of %zu used bytes", - humongous_regions_promoted, regular_regions_promoted_in_place, - humongous_regions_promoted * ShenandoahHeapRegion::region_size_bytes() + - regular_regions_promoted_usage); // Step 2. Look back at garbage statistics, and decide if we want to collect anything, // given the amount of immediately reclaimable garbage. If we do, figure out the collection set. + assert(immediate_garbage <= total_garbage, + "Cannot have more immediate garbage than total garbage: " PROPERFMT " vs " PROPERFMT, + PROPERFMTARGS(immediate_garbage), PROPERFMTARGS(total_garbage)); - assert (immediate_garbage <= total_garbage, - "Cannot have more immediate garbage than total garbage: %zu%s vs %zu%s", - byte_size_in_proper_unit(immediate_garbage), proper_unit_for_byte_size(immediate_garbage), - byte_size_in_proper_unit(total_garbage), proper_unit_for_byte_size(total_garbage)); - - size_t immediate_percent = (total_garbage == 0) ? 0 : (immediate_garbage * 100 / total_garbage); - bool doing_promote_in_place = (humongous_regions_promoted + regular_regions_promoted_in_place > 0); - - if (doing_promote_in_place || (preselected_candidates > 0) || (immediate_percent <= ShenandoahImmediateThreshold)) { + const size_t immediate_percent = (total_garbage == 0) ? 0 : (immediate_garbage * 100 / total_garbage); + const bool has_preselected_regions = !collection_set->is_empty(); + if (has_preselected_regions || (immediate_percent <= ShenandoahImmediateThreshold)) { // Call the subclasses to add young-gen regions into the collection set. choose_collection_set_from_regiondata(collection_set, candidates, cand_idx, immediate_garbage + free); } @@ -376,15 +324,15 @@ void ShenandoahGenerationalHeuristics::filter_regions(ShenandoahCollectionSet* c ShenandoahTracer::report_evacuation_info(collection_set, free_regions, - humongous_regions_promoted, - regular_regions_promoted_in_place, - regular_regions_promoted_garbage, - regular_regions_promoted_free, + in_place_promotions.humongous_region_stats().count, + in_place_promotions.regular_region_stats().count, + in_place_promotions.regular_region_stats().garbage, + in_place_promotions.regular_region_stats().free, immediate_regions, immediate_garbage); } -// Preselect for inclusion into the collection set all regions whose age is at or above tenure age and for which the +// Select for inclusion into the collection set all regions whose age is at or above tenure age and for which the // garbage percentage exceeds a dynamically adjusted threshold (known as the old-garbage threshold percentage). We // identify these regions by setting the appropriate entry of the collection set's preselected regions array to true. // All entries are initialized to false before calling this function. @@ -400,15 +348,13 @@ void ShenandoahGenerationalHeuristics::filter_regions(ShenandoahCollectionSet* c // that this allows us to more accurately budget memory to hold the results of evacuation. Memory for evacuation // of aged regions must be reserved in the old generation. Memory for evacuation of all other regions must be // reserved in the young generation. -size_t ShenandoahGenerationalHeuristics::select_aged_regions(const size_t old_promotion_reserve) { +size_t ShenandoahGenerationalHeuristics::select_aged_regions(ShenandoahInPlacePromotionPlanner& in_place_promotions, + const size_t old_promotion_reserve) { // There should be no regions configured for subsequent in-place-promotions carried over from the previous cycle. assert_no_in_place_promotions(); auto const heap = ShenandoahGenerationalHeap::heap(); - ShenandoahFreeSet* free_set = heap->free_set(); - bool* const candidate_regions_for_promotion_by_copy = heap->collection_set()->preselected_regions(); - ShenandoahMarkingContext* const ctx = heap->marking_context(); size_t promo_potential = 0; size_t candidates = 0; @@ -421,14 +367,21 @@ size_t ShenandoahGenerationalHeuristics::select_aged_regions(const size_t old_pr ResourceMark rm; AgedRegionData* sorted_regions = NEW_RESOURCE_ARRAY(AgedRegionData, num_regions); - ShenandoahInPlacePromotionPlanner in_place_promotions(heap); - for (idx_t i = 0; i < num_regions; i++) { ShenandoahHeapRegion* const r = heap->get_region(i); - if (r->is_empty() || !r->has_live() || !r->is_young() || !r->is_regular()) { - // skip over regions that aren't regular young with some live data + if (r->is_empty() || !r->has_live() || !r->is_young()) { + // skip over regions that aren't young with some live data continue; } + + if (!r->is_regular()) { + if (r->is_humongous() && heap->is_tenurable(r)) { + in_place_promotions.prepare(r); + } + // Nothing else to be done for humongous regions + continue; + } + if (heap->is_tenurable(r)) { if (in_place_promotions.is_eligible(r)) { // We prefer to promote this region in place because it has a small amount of garbage and a large usage. @@ -470,7 +423,7 @@ size_t ShenandoahGenerationalHeuristics::select_aged_regions(const size_t old_pr // Subsequent regions may be selected if they have smaller live data. } - in_place_promotions.update_free_set(); + in_place_promotions.complete_planning(); // Sort in increasing order according to live data bytes. Note that candidates represents the number of regions // that qualify to be promoted by evacuation. @@ -485,14 +438,14 @@ size_t ShenandoahGenerationalHeuristics::select_aged_regions(const size_t old_pr const size_t promotion_need = (size_t) (region_live_data * ShenandoahPromoEvacWaste); if (old_consumed + promotion_need <= old_promotion_reserve) { old_consumed += promotion_need; - candidate_regions_for_promotion_by_copy[region->index()] = true; + heap->collection_set()->add_region(region); selected_regions++; selected_live += region_live_data; } else { // We rejected this promotable region from the collection set because we had no room to hold its copy. // Add this region to promo potential for next GC. promo_potential += region_live_data; - assert(!candidate_regions_for_promotion_by_copy[region->index()], "Shouldn't be selected"); + assert(!heap->collection_set()->is_in(region), "Region %zu shouldn't be in the collection set", region->index()); } // We keep going even if one region is excluded from selection because we need to accumulate all eligible // regions that are not preselected into promo_potential @@ -561,7 +514,7 @@ void ShenandoahGenerationalHeuristics::adjust_evacuation_budgets(ShenandoahHeap* young_evacuated_reserve_used, total_young_available); young_generation->set_evacuation_reserve(young_evacuated_reserve_used); - // We have not yet rebuilt the free set. Some of the memory that is thought to be avaiable within old may no + // We have not yet rebuilt the free set. Some of the memory that is thought to be available within old may no // longer be available if that memory had been free within regions that were selected for the collection set. // Make the necessary adjustments to old_available. size_t old_available = @@ -640,24 +593,3 @@ void ShenandoahGenerationalHeuristics::adjust_evacuation_budgets(ShenandoahHeap* old_generation->set_promoted_reserve(total_promotion_reserve); old_generation->reset_promoted_expended(); } - -size_t ShenandoahGenerationalHeuristics::add_preselected_regions_to_collection_set(ShenandoahCollectionSet* cset, - const RegionData* data, - size_t size) const { - // cur_young_garbage represents the amount of memory to be reclaimed from young-gen. In the case that live objects - // are known to be promoted out of young-gen, we count this as cur_young_garbage because this memory is reclaimed - // from young-gen and becomes available to serve future young-gen allocation requests. - size_t cur_young_garbage = 0; - for (size_t idx = 0; idx < size; idx++) { - ShenandoahHeapRegion* r = data[idx].get_region(); - if (cset->is_preselected(r->index())) { - assert(ShenandoahGenerationalHeap::heap()->is_tenurable(r), "Preselected regions must have tenure age"); - // Entire region will be promoted, This region does not impact young-gen or old-gen evacuation reserve. - // This region has been pre-selected and its impact on promotion reserve is already accounted for. - cur_young_garbage += r->garbage(); - cset->add_region(r); - } - } - return cur_young_garbage; -} - diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp index da883d0d26f..248d0de5a26 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.hpp @@ -27,6 +27,7 @@ #include "gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp" +#include "gc/shenandoah/shenandoahInPlacePromoter.hpp" class ShenandoahGeneration; class ShenandoahHeap; @@ -53,7 +54,7 @@ public: private: // Compute evacuation budgets prior to choosing collection set. - void compute_evacuation_budgets(ShenandoahHeap* const heap); + void compute_evacuation_budgets(ShenandoahInPlacePromotionPlanner& in_place_promotions, ShenandoahHeap* const heap); // Preselect for possible inclusion into the collection set exactly the most // garbage-dense regions, including those that satisfy criteria 1 & 2 below, @@ -70,10 +71,10 @@ private: // regions, which are marked in the preselected_regions() indicator // array of the heap's collection set, which should be initialized // to false. - size_t select_aged_regions(const size_t old_promotion_reserve); + size_t select_aged_regions(ShenandoahInPlacePromotionPlanner& in_place_promotions, const size_t old_promotion_reserve); // Filter and sort remaining regions before adding to collection set. - void filter_regions(ShenandoahCollectionSet* collection_set); + void filter_regions(ShenandoahInPlacePromotionPlanner& in_place_promotions, ShenandoahCollectionSet* collection_set); // Adjust evacuation budgets after choosing collection set. The argument regions_to_xfer // represents regions to be transferred to old based on decisions made in top_off_collection_set() @@ -84,10 +85,6 @@ protected: ShenandoahGeneration* _generation; size_t _add_regions_to_old; - - size_t add_preselected_regions_to_collection_set(ShenandoahCollectionSet* cset, - const RegionData* data, - size_t size) const; }; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp index dd2ad28aa4b..142a6c3f047 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGlobalHeuristics.cpp @@ -127,7 +127,7 @@ void ShenandoahGlobalHeuristics::choose_global_collection_set(ShenandoahCollecti size_t cur_garbage = cur_young_garbage; for (size_t idx = 0; idx < size; idx++) { ShenandoahHeapRegion* r = data[idx].get_region(); - assert(!cset->is_preselected(r->index()), "There should be no preselected regions during GLOBAL GC"); + assert(!cset->is_in(r->index()), "Region (%zu) should not be in the collection set", r->index()); bool add_region = false; size_t region_garbage = r->garbage(); size_t new_garbage = cur_garbage + region_garbage; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp index 603e00c401d..895088381ee 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp @@ -122,13 +122,7 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec } } else if (region->is_humongous_start()) { // Reclaim humongous regions here, and count them as the immediate garbage -#ifdef ASSERT - bool reg_live = region->has_live(); - bool bm_live = heap->global_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); - assert(reg_live == bm_live, - "Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu", - BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words()); -#endif + DEBUG_ONLY(assert_humongous_mark_consistency(region)); if (!region->has_live()) { heap->trash_humongous_region_at(region); @@ -137,7 +131,7 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec immediate_garbage += garbage; } } else if (region->is_trash()) { - // Count in just trashed collection set, during coalesced CM-with-UR + // Count in just trashed humongous continuation regions immediate_regions++; immediate_garbage += garbage; } @@ -145,13 +139,11 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec // Step 2. Look back at garbage statistics, and decide if we want to collect anything, // given the amount of immediately reclaimable garbage. If we do, figure out the collection set. + assert(immediate_garbage <= total_garbage, + "Cannot have more immediate garbage than total garbage: " PROPERFMT " vs " PROPERFMT, + PROPERFMTARGS(immediate_garbage), PROPERFMTARGS(total_garbage)); - assert (immediate_garbage <= total_garbage, - "Cannot have more immediate garbage than total garbage: %zu%s vs %zu%s", - byte_size_in_proper_unit(immediate_garbage), proper_unit_for_byte_size(immediate_garbage), - byte_size_in_proper_unit(total_garbage), proper_unit_for_byte_size(total_garbage)); - - size_t immediate_percent = (total_garbage == 0) ? 0 : (immediate_garbage * 100 / total_garbage); + const size_t immediate_percent = (total_garbage == 0) ? 0 : (immediate_garbage * 100 / total_garbage); if (immediate_percent <= ShenandoahImmediateThreshold) { choose_collection_set_from_regiondata(collection_set, candidates, cand_idx, immediate_garbage + free); @@ -303,3 +295,16 @@ double ShenandoahHeuristics::elapsed_degenerated_cycle_time() const { double now = os::elapsedTime(); return now - _precursor_cycle_start; } + +#ifdef ASSERT +void ShenandoahHeuristics::assert_humongous_mark_consistency(ShenandoahHeapRegion* region) { + assert(region->is_humongous(), "Region %zu must be humongous", region->index()); + const oop humongous_oop = cast_to_oop(region->bottom()); + ShenandoahGeneration* generation = ShenandoahHeap::heap()->generation_for(region->affiliation()); + const bool bm_live = generation->complete_marking_context()->is_marked(humongous_oop); + const bool reg_live = region->has_live(); + assert(reg_live == bm_live, + "Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu", + BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words()); +} +#endif diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp index 5bfba4f52d5..9066cdfccac 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.hpp @@ -285,6 +285,8 @@ public: // Format prefix and emit log message indicating a GC cycle hs been triggered void log_trigger(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3); + + DEBUG_ONLY(static void assert_humongous_mark_consistency(ShenandoahHeapRegion* region)); }; #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp index 09508a1163f..3779f969723 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp @@ -54,9 +54,7 @@ void ShenandoahYoungHeuristics::choose_collection_set_from_regiondata(Shenandoah // Better select garbage-first regions QuickSort::sort(data, size, compare_by_garbage); - size_t cur_young_garbage = add_preselected_regions_to_collection_set(cset, data, size); - - choose_young_collection_set(cset, data, size, actual_free, cur_young_garbage); + choose_young_collection_set(cset, data, size, actual_free); // Especially when young-gen trigger is expedited in order to finish mixed evacuations, there may not be // enough consolidated garbage to make effective use of young-gen evacuation reserve. If there is still @@ -70,8 +68,7 @@ void ShenandoahYoungHeuristics::choose_collection_set_from_regiondata(Shenandoah void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollectionSet* cset, const RegionData* data, - size_t size, size_t actual_free, - size_t cur_young_garbage) const { + size_t size, size_t actual_free) const { const auto heap = ShenandoahGenerationalHeap::heap(); @@ -82,23 +79,20 @@ void ShenandoahYoungHeuristics::choose_young_collection_set(ShenandoahCollection // This is young-gen collection or a mixed evacuation. // If this is mixed evacuation, the old-gen candidate regions have already been added. size_t cur_cset = 0; + size_t cur_young_garbage = cset->garbage(); const size_t max_cset = (size_t) (heap->young_generation()->get_evacuation_reserve() / ShenandoahEvacWaste); const size_t free_target = (capacity * ShenandoahMinFreeThreshold) / 100 + max_cset; const size_t min_garbage = (free_target > actual_free) ? (free_target - actual_free) : 0; - log_info(gc, ergo)( - "Adaptive CSet Selection for YOUNG. Max Evacuation: %zu%s, Actual Free: %zu%s.", - byte_size_in_proper_unit(max_cset), proper_unit_for_byte_size(max_cset), - byte_size_in_proper_unit(actual_free), proper_unit_for_byte_size(actual_free)); + "Adaptive CSet Selection for YOUNG. Max Evacuation: " PROPERFMT ", Actual Free: " PROPERFMT, + PROPERFMTARGS(max_cset), PROPERFMTARGS(actual_free)); for (size_t idx = 0; idx < size; idx++) { ShenandoahHeapRegion* r = data[idx].get_region(); - if (cset->is_preselected(r->index())) { - continue; - } + assert(!cset->is_in(r), "Region %zu should not already be in the collection set", idx); - // Note that we do not add tenurable regions if they were not pre-selected. They were not preselected + // Note that we do not add tenurable regions if they were not pre-selected. They were not selected // because there is insufficient room in old-gen to hold their to-be-promoted live objects or because // they are to be promoted in place. if (!heap->is_tenurable(r)) { diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp index b9d64059680..806cef673d5 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp @@ -49,8 +49,7 @@ public: private: void choose_young_collection_set(ShenandoahCollectionSet* cset, const RegionData* data, - size_t size, size_t actual_free, - size_t cur_young_garbage) const; + size_t size, size_t actual_free) const; }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp index 54ab7801ca9..d2a489a15be 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp @@ -49,7 +49,6 @@ ShenandoahCollectionSet::ShenandoahCollectionSet(ShenandoahHeap* heap, ReservedS _live(0), _region_count(0), _old_garbage(0), - _preselected_regions(nullptr), _young_available_bytes_collected(0), _old_available_bytes_collected(0), _current_index(0) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp index 87b4597c93f..7722423709d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp @@ -36,13 +36,6 @@ class ShenandoahCollectionSet : public CHeapObj { friend class ShenandoahHeap; - friend class ShenandoahCollectionSetPreselector; - - void establish_preselected(bool *preselected) { - assert(_preselected_regions == nullptr, "Over-writing"); - _preselected_regions = preselected; - } - void abandon_preselected() { _preselected_regions = nullptr; } private: size_t const _map_size; @@ -67,11 +60,6 @@ private: // How many bytes of old garbage are present in a mixed collection set? size_t _old_garbage; - // Points to array identifying which tenure-age regions have been preselected - // for inclusion in collection set. This field is only valid during brief - // spans of time while collection set is being constructed. - bool* _preselected_regions; - // When a region having memory available to be allocated is added to the collection set, the region's available memory // should be subtracted from what's available. size_t _young_available_bytes_collected; @@ -132,16 +120,6 @@ public: // Returns the amount of garbage in old regions in the collection set. inline size_t get_old_garbage() const; - bool is_preselected(size_t region_idx) { - assert(_preselected_regions != nullptr, "Missing establish after abandon"); - return _preselected_regions[region_idx]; - } - - bool* preselected_regions() { - assert(_preselected_regions != nullptr, "Null ptr"); - return _preselected_regions; - } - bool has_old_regions() const { return _has_old_regions; } size_t used() const { return _used; } size_t live() const { return _live; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSetPreselector.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSetPreselector.hpp deleted file mode 100644 index b78259dd85b..00000000000 --- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSetPreselector.hpp +++ /dev/null @@ -1,51 +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. - * - */ - -#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCOLLECTIONSETPRESELECTOR_HPP -#define SHARE_GC_SHENANDOAH_SHENANDOAHCOLLECTIONSETPRESELECTOR_HPP - -#include "gc/shenandoah/shenandoahCollectionSet.hpp" -#include "memory/resourceArea.hpp" - -class ShenandoahCollectionSetPreselector : public StackObj { - ShenandoahCollectionSet* _cset; - bool* _pset; - ResourceMark _rm; - -public: - ShenandoahCollectionSetPreselector(ShenandoahCollectionSet* cset, size_t num_regions): - _cset(cset) { - _pset = NEW_RESOURCE_ARRAY(bool, num_regions); - for (unsigned int i = 0; i < num_regions; i++) { - _pset[i] = false; - } - _cset->establish_preselected(_pset); - } - - ~ShenandoahCollectionSetPreselector() { - _cset->abandon_preselected(); - } -}; - -#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCOLLECTIONSETPRESELECTOR_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp index 83f4217df83..4a15401250c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.cpp @@ -26,38 +26,11 @@ #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahGenerationalHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" -#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahInPlacePromoter.hpp" #include "gc/shenandoah/shenandoahMarkingContext.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahYoungGeneration.hpp" -ShenandoahInPlacePromotionPlanner::RegionPromotions::RegionPromotions(ShenandoahFreeSet* free_set) - : _low_idx(free_set->max_regions()) - , _high_idx(-1) - , _regions(0) - , _bytes(0) - , _free_set(free_set) -{ -} - -void ShenandoahInPlacePromotionPlanner::RegionPromotions::increment(idx_t region_index, size_t remnant_bytes) { - if (region_index < _low_idx) { - _low_idx = region_index; - } - if (region_index > _high_idx) { - _high_idx = region_index; - } - _regions++; - _bytes += remnant_bytes; -} - -void ShenandoahInPlacePromotionPlanner::RegionPromotions::update_free_set(ShenandoahFreeSetPartitionId partition_id) const { - if (_regions > 0) { - _free_set->shrink_interval_if_range_modifies_either_boundary(partition_id, _low_idx, _high_idx, _regions); - } -} - ShenandoahInPlacePromotionPlanner::ShenandoahInPlacePromotionPlanner(const ShenandoahGenerationalHeap* heap) : _old_garbage_threshold(ShenandoahHeapRegion::region_size_bytes() * heap->old_generation()->heuristics()->get_old_garbage_threshold() / 100) , _pip_used_threshold(ShenandoahHeapRegion::region_size_bytes() * ShenandoahGenerationalMinPIPUsage / 100) @@ -86,6 +59,14 @@ void ShenandoahInPlacePromotionPlanner::prepare(ShenandoahHeapRegion* r) { return; } + if (r->is_humongous()) { + // Nothing else to do for humongous, we just update the stats and move on. The humongous regions + // themselves will be discovered and promoted by gc workers during evacuation. + _pip_humongous_stats.update(r); + return; + } + + _pip_regular_stats.update(r); // No allocations from this region have been made during concurrent mark. It meets all the criteria // for in-place-promotion. Though we only need the value of top when we fill the end of the region, // we use this field to indicate that this region should be promoted in place during the evacuation @@ -128,8 +109,14 @@ void ShenandoahInPlacePromotionPlanner::prepare(ShenandoahHeapRegion* r) { } } -void ShenandoahInPlacePromotionPlanner::update_free_set() const { +void ShenandoahInPlacePromotionPlanner::complete_planning() const { _heap->old_generation()->set_pad_for_promote_in_place(_pip_padding_bytes); + _heap->old_generation()->set_expected_humongous_region_promotions(_pip_humongous_stats.count); + _heap->old_generation()->set_expected_regular_region_promotions(_pip_regular_stats.count); + log_info(gc, ergo)("Planning to promote in place %zu humongous regions and %zu" + " regular regions, spanning a total of %zu used bytes", + _pip_humongous_stats.count, _pip_regular_stats.count, + _pip_humongous_stats.usage + _pip_regular_stats.usage); if (_mutator_regions._regions + _collector_regions._regions > 0) { _free_set->account_for_pip_regions(_mutator_regions._regions, _mutator_regions._bytes, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp index 939107dd3ac..2e7e19ee26e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInPlacePromoter.hpp @@ -25,16 +25,21 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHINPLACEPROMOTER_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHINPLACEPROMOTER_HPP +#include "gc/shenandoah/shenandoahFreeSet.hpp" +#include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahSimpleBitMap.hpp" -class ShenandoahFreeSet; class ShenandoahMarkingContext; class ShenandoahGenerationalHeap; -class ShenandoahHeapRegion; +// This class is responsible for identifying regions that can be +// promoted in place. It also prepares these regions by preventing +// them from being used for allocations. Finally, it notifies the +// freeset which regions are to be promoted in place. class ShenandoahInPlacePromotionPlanner { using idx_t = ShenandoahSimpleBitMap::idx_t; + // Used to inform free set of regions being promoted struct RegionPromotions { idx_t _low_idx; idx_t _high_idx; @@ -42,9 +47,47 @@ class ShenandoahInPlacePromotionPlanner { size_t _bytes; ShenandoahFreeSet* _free_set; - explicit RegionPromotions(ShenandoahFreeSet* free_set); - void increment(idx_t region_index, size_t remnant_bytes); - void update_free_set(ShenandoahFreeSetPartitionId partition_id) const; + explicit RegionPromotions(ShenandoahFreeSet* free_set) + : _low_idx(free_set->max_regions()) + , _high_idx(-1) + , _regions(0) + , _bytes(0) + , _free_set(free_set) + { + } + + void increment(idx_t region_index, size_t remnant_bytes) { + if (region_index < _low_idx) { + _low_idx = region_index; + } + if (region_index > _high_idx) { + _high_idx = region_index; + } + _regions++; + _bytes += remnant_bytes; + } + + void update_free_set(ShenandoahFreeSetPartitionId partition_id) const { + if (_regions > 0) { + _free_set->shrink_interval_if_range_modifies_either_boundary(partition_id, _low_idx, _high_idx, _regions); + } + } + }; + + // Used to track metrics about the regions being promoted in place + struct RegionPromotionStats { + size_t count; + size_t usage; + size_t free; + size_t garbage; + + RegionPromotionStats() : count(0), usage(0), free(0), garbage(0) {} + void update(ShenandoahHeapRegion* region) { + count++; + usage += region->used(); + free += region->free(); + garbage += region->garbage(); + } }; const size_t _old_garbage_threshold; @@ -60,6 +103,11 @@ class ShenandoahInPlacePromotionPlanner { // Tracks the padding of space above top in regions eligible for promotion in place size_t _pip_padding_bytes; + + // Tracks stats for in place promotions + RegionPromotionStats _pip_regular_stats; + RegionPromotionStats _pip_humongous_stats; + public: explicit ShenandoahInPlacePromotionPlanner(const ShenandoahGenerationalHeap* heap); @@ -69,12 +117,17 @@ public: // Prepares the region for promotion by moving top to the end to prevent allocations void prepare(ShenandoahHeapRegion* region); - // Notifies the free set of in place promotions - void update_free_set() const; + // Notifies the free set and old generation of in place promotions + void complete_planning() const; + + const RegionPromotionStats& regular_region_stats() const { return _pip_regular_stats; } + const RegionPromotionStats& humongous_region_stats() const { return _pip_humongous_stats; } size_t old_garbage_threshold() const { return _old_garbage_threshold; } }; +// For regions that have been selected and prepared for promotion, this class +// will perform the actual promotion. class ShenandoahInPlacePromoter { ShenandoahGenerationalHeap* _heap; public: From 3e9fc5d49e52d79bcd2bb75068ff7efb31f768fd Mon Sep 17 00:00:00 2001 From: wuxinyang Date: Tue, 10 Mar 2026 02:15:25 +0000 Subject: [PATCH 135/170] 8376164: Optimize AES/ECB implementation using full-message intrinsic stub and parallel RoundKey addition Reviewed-by: sviswanathan, semery --- src/hotspot/cpu/x86/stubGenerator_x86_64.hpp | 15 +- .../cpu/x86/stubGenerator_x86_64_aes.cpp | 200 +++++++++++++++++- 2 files changed, 212 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 36315535d16..64b56442c90 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -330,6 +330,19 @@ class StubGenerator: public StubCodeGenerator { void aesecb_decrypt(Register source_addr, Register dest_addr, Register key, Register len); + // Shared implementation for ECB/AES Encrypt and Decrypt, which does 4 blocks + // in a loop at a time to hide instruction latency. Set is_encrypt=true for + // encryption, false for decryption. + address generate_electronicCodeBook_AESCrypt_Parallel(bool is_encrypt); + + // A version of ECB/AES Encrypt which does 4 blocks in a loop at a time + // to hide instruction latency + address generate_electronicCodeBook_encryptAESCrypt_Parallel(); + + // A version of ECB/AES Decrypt which does 4 blocks in a loop at a time + // to hide instruction latency + address generate_electronicCodeBook_decryptAESCrypt_Parallel(); + // Vector AES Galois Counter Mode implementation address generate_galoisCounterMode_AESCrypt(); void aesgcm_encrypt(Register in, Register len, Register ct, Register out, Register key, diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp index 24de32a6fe7..1fa80c9d967 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_aes.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2019, 2025, Intel Corporation. All rights reserved. +* Copyright (c) 2019, 2026, Intel Corporation. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -218,6 +218,8 @@ void StubGenerator::generate_aes_stubs() { StubRoutines::_galoisCounterMode_AESCrypt = generate_galoisCounterMode_AESCrypt(); } else { StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel(); + StubRoutines::_electronicCodeBook_encryptAESCrypt = generate_electronicCodeBook_encryptAESCrypt_Parallel(); + StubRoutines::_electronicCodeBook_decryptAESCrypt = generate_electronicCodeBook_decryptAESCrypt_Parallel(); if (VM_Version::supports_avx2()) { StubRoutines::_galoisCounterMode_AESCrypt = generate_avx2_galoisCounterMode_AESCrypt(); } @@ -1399,6 +1401,200 @@ address StubGenerator::generate_cipherBlockChaining_encryptAESCrypt() { return start; } +// This is a version of ECB/AES Encrypt/Decrypt which does 4 blocks in a loop +// at a time to hide instruction latency. +// +// For encryption (is_encrypt=true): +// pxor key[0], aesenc key[1..rounds-1], aesenclast key[rounds] +// For decryption (is_encrypt=false): +// pxor key[1], aesdec key[2..rounds], aesdeclast key[0] +// +// Arguments: +// +// Inputs: +// c_rarg0 - source byte array address +// c_rarg1 - destination byte array address +// c_rarg2 - session key (Ke/Kd) in little endian int array +// c_rarg3 - input length (must be multiple of blocksize 16) +// +// Output: +// rax - input length +// +address StubGenerator::generate_electronicCodeBook_AESCrypt_Parallel(bool is_encrypt) { + assert(UseAES, "need AES instructions and misaligned SSE support"); + __ align(CodeEntryAlignment); + StubId stub_id = is_encrypt ? StubId::stubgen_electronicCodeBook_encryptAESCrypt_id + : StubId::stubgen_electronicCodeBook_decryptAESCrypt_id; + StubCodeMark mark(this, stub_id); + address start = __ pc(); + + const Register from = c_rarg0; // source array address + const Register to = c_rarg1; // destination array address + const Register key = c_rarg2; // key array address + const Register len_reg = c_rarg3; // src len (must be multiple of blocksize 16) + const Register pos = rax; + const Register keylen = r11; + + const XMMRegister xmm_result0 = xmm0; + const XMMRegister xmm_result1 = xmm1; + const XMMRegister xmm_result2 = xmm2; + const XMMRegister xmm_result3 = xmm3; + const XMMRegister xmm_key_shuf_mask = xmm4; + const XMMRegister xmm_key_tmp = xmm5; + // keys 0-9 pre-loaded into xmm6-xmm15 + const int XMM_REG_NUM_KEY_FIRST = 6; + const int XMM_REG_NUM_KEY_LAST = 15; + const XMMRegister xmm_key_first = as_XMMRegister(XMM_REG_NUM_KEY_FIRST); + + // for key_128, key_192, key_256 + const int ROUNDS[3] = {10, 12, 14}; + + Label L_exit; + Label L_loop4[3], L_single[3], L_done[3]; + +#ifdef DoFour +#undef DoFour +#endif +#ifdef DoOne +#undef DoOne +#endif + +#define DoFour(opc, reg) \ +__ opc(xmm_result0, reg); \ +__ opc(xmm_result1, reg); \ +__ opc(xmm_result2, reg); \ +__ opc(xmm_result3, reg); + +#define DoOne(opc, reg) \ +__ opc(xmm_result0, reg); + + __ enter(); // required for proper stackwalking of RuntimeStub frame + __ push(len_reg); // save original length for return value + + __ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); + + __ movdqu(xmm_key_shuf_mask, ExternalAddress(key_shuffle_mask_addr()), r10 /*rscratch*/); + // load up xmm regs 6 thru 15 with keys 0x00 - 0x90 + for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x00; rnum <= XMM_REG_NUM_KEY_LAST; rnum++, offset += 0x10) { + load_key(as_XMMRegister(rnum), key, offset, xmm_key_shuf_mask); + } + __ xorptr(pos, pos); + + // key length could be only {11, 13, 15} * 4 = {44, 52, 60} + __ cmpl(keylen, 52); + __ jcc(Assembler::equal, L_loop4[1]); + __ cmpl(keylen, 60); + __ jcc(Assembler::equal, L_loop4[2]); + + // k == 0: generate code for key_128 + // k == 1: generate code for key_192 + // k == 2: generate code for key_256 + for (int k = 0; k < 3; ++k) { + __ align(OptoLoopAlignment); + __ BIND(L_loop4[k]); + __ cmpptr(len_reg, 4 * AESBlockSize); + __ jcc(Assembler::less, L_single[k]); + + __ movdqu(xmm_result0, Address(from, pos, Address::times_1, 0 * AESBlockSize)); + __ movdqu(xmm_result1, Address(from, pos, Address::times_1, 1 * AESBlockSize)); + __ movdqu(xmm_result2, Address(from, pos, Address::times_1, 2 * AESBlockSize)); + __ movdqu(xmm_result3, Address(from, pos, Address::times_1, 3 * AESBlockSize)); + + if (is_encrypt) { + DoFour(pxor, xmm_key_first); + for (int rnum = 1; rnum < 10; rnum++) { + DoFour(aesenc, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); + } + for (int i = 10; i < ROUNDS[k]; i++) { + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); + DoFour(aesenc, xmm_key_tmp); + } + load_key(xmm_key_tmp, key, ROUNDS[k] * 0x10, xmm_key_shuf_mask); + DoFour(aesenclast, xmm_key_tmp); + } else { + DoFour(pxor, as_XMMRegister(1 + XMM_REG_NUM_KEY_FIRST)); + for (int rnum = 2; rnum < 10; rnum++) { + DoFour(aesdec, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); + } + for (int i = 10; i <= ROUNDS[k]; i++) { + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); + DoFour(aesdec, xmm_key_tmp); + } + DoFour(aesdeclast, xmm_key_first); + } + + __ movdqu(Address(to, pos, Address::times_1, 0 * AESBlockSize), xmm_result0); + __ movdqu(Address(to, pos, Address::times_1, 1 * AESBlockSize), xmm_result1); + __ movdqu(Address(to, pos, Address::times_1, 2 * AESBlockSize), xmm_result2); + __ movdqu(Address(to, pos, Address::times_1, 3 * AESBlockSize), xmm_result3); + + __ addptr(pos, 4 * AESBlockSize); + __ subptr(len_reg, 4 * AESBlockSize); + __ jmp(L_loop4[k]); + + __ align(OptoLoopAlignment); + __ BIND(L_single[k]); + __ cmpptr(len_reg, AESBlockSize); + __ jcc(Assembler::less, L_done[k]); + + __ movdqu(xmm_result0, Address(from, pos, Address::times_1, 0)); + + if (is_encrypt) { + DoOne(pxor, xmm_key_first); + for (int rnum = 1; rnum < 10; rnum++) { + DoOne(aesenc, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); + } + for (int i = 10; i < ROUNDS[k]; i++) { + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); + DoOne(aesenc, xmm_key_tmp); + } + load_key(xmm_key_tmp, key, ROUNDS[k] * 0x10, xmm_key_shuf_mask); + DoOne(aesenclast, xmm_key_tmp); + } else { + DoOne(pxor, as_XMMRegister(1 + XMM_REG_NUM_KEY_FIRST)); + for (int rnum = 2; rnum < 10; rnum++) { + DoOne(aesdec, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); + } + for (int i = 10; i <= ROUNDS[k]; i++) { + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); + DoOne(aesdec, xmm_key_tmp); + } + DoOne(aesdeclast, xmm_key_first); + } + + __ movdqu(Address(to, pos, Address::times_1, 0), xmm_result0); + __ addptr(pos, AESBlockSize); + __ subptr(len_reg, AESBlockSize); + __ jmp(L_single[k]); + + __ BIND(L_done[k]); + if (k < 2) __ jmp(L_exit); + } //for key_128/192/256 + + __ BIND(L_exit); + // Clear all XMM registers holding sensitive key material before returning + __ pxor(xmm_key_tmp, xmm_key_tmp); + for (int rnum = XMM_REG_NUM_KEY_FIRST; rnum <= XMM_REG_NUM_KEY_LAST; rnum++) { + __ pxor(as_XMMRegister(rnum), as_XMMRegister(rnum)); + } + __ pop(rax); + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; + +#undef DoFour +#undef DoOne +} + +address StubGenerator::generate_electronicCodeBook_encryptAESCrypt_Parallel() { + return generate_electronicCodeBook_AESCrypt_Parallel(true); +} + +address StubGenerator::generate_electronicCodeBook_decryptAESCrypt_Parallel() { + return generate_electronicCodeBook_AESCrypt_Parallel(false); +} + // This is a version of CBC/AES Decrypt which does 4 blocks in a loop at a time // to hide instruction latency // @@ -1493,7 +1689,7 @@ address StubGenerator::generate_cipherBlockChaining_decryptAESCrypt_Parallel() { __ opc(xmm_result0, src_reg); \ __ opc(xmm_result1, src_reg); \ __ opc(xmm_result2, src_reg); \ -__ opc(xmm_result3, src_reg); \ +__ opc(xmm_result3, src_reg); for (int k = 0; k < 3; ++k) { __ BIND(L_multiBlock_loopTopHead[k]); From 9a26b4af34cd3e8690c5150da232eaa8bf3a82a6 Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Tue, 10 Mar 2026 03:56:28 +0000 Subject: [PATCH 136/170] 8379372: Enable some vector algorithms IR matching tests for RISC-V Reviewed-by: fyang --- .../vectorization/TestVectorAlgorithms.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java index ed04950eb07..f11955bef86 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorAlgorithms.java @@ -262,11 +262,11 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.REPLICATE_I, "= 1", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIfAnd = {"UseSuperWord", "true", "OptimizeFill", "false"}) @IR(counts = {".*CallLeafNoFP.*jint_fill.*", "= 1"}, phase = CompilePhase.BEFORE_MATCHING, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"OptimizeFill", "true"}) // By default, the fill intrinsic "jint_fill" is used, but we can disable // the detection of the fill loop, and then we auto vectorize. @@ -277,7 +277,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.REPLICATE_I, "= 1", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public Object fillI_VectorAPI(int[] r) { return VectorAlgorithmsImpl.fillI_VectorAPI(r); } @@ -292,7 +292,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.POPULATE_INDEX, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"avx2", "true", "sve", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "sve", "true", "rvv", "true"}, applyIf = {"UseSuperWord", "true"}) // Note: the Vector API example below can also vectorize for AVX, // because it does not use a PopulateIndex. @@ -303,7 +303,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.ADD_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"TieredCompilation", "true"}) // IR check only works with TieredCompilation. Needs to make it // work with -XX:-TieredCompilation in future (see JDK-8378640). @@ -314,7 +314,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"UseSuperWord", "true"}) public Object copyI_loop(int[] a, int[] r) { return VectorAlgorithmsImpl.copyI_loop(a, r); @@ -323,7 +323,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public Object copyI_VectorAPI(int[] a, int[] r) { return VectorAlgorithmsImpl.copyI_VectorAPI(a, r); } @@ -331,7 +331,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {".*CallLeafNoFP.*jint_disjoint_arraycopy.*", "= 1"}, phase = CompilePhase.BEFORE_MATCHING, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public Object copyI_System_arraycopy(int[] a, int[] r) { return VectorAlgorithmsImpl.copyI_System_arraycopy(a, r); } @@ -340,7 +340,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"UseSuperWord", "true"}) public Object mapI_loop(int[] a, int[] r) { return VectorAlgorithmsImpl.mapI_loop(a, r); @@ -350,7 +350,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public Object mapI_VectorAPI(int[] a, int[] r) { return VectorAlgorithmsImpl.mapI_VectorAPI(a, r); } @@ -359,7 +359,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.ADD_REDUCTION_VI, "> 0", IRNode.ADD_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"UseSuperWord", "true"}) public int reduceAddI_loop(int[] a) { return VectorAlgorithmsImpl.reduceAddI_loop(a); @@ -373,7 +373,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.ADD_REDUCTION_VI, "> 0"}, // reduceLanes inside loop - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public int reduceAddI_VectorAPI_naive(int[] a) { return VectorAlgorithmsImpl.reduceAddI_VectorAPI_naive(a); } @@ -393,7 +393,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.ADD_REDUCTION_V, "> 0", IRNode.MUL_VF, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"UseSuperWord", "true"}) public float dotProductF_VectorAPI_naive(float[] a, float[] b) { return VectorAlgorithmsImpl.dotProductF_VectorAPI_naive(a, b); @@ -403,7 +403,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.ADD_REDUCTION_V, "> 0", IRNode.MUL_VF, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"UseSuperWord", "true"}) public float dotProductF_VectorAPI_reduction_after_loop(float[] a, float[] b) { return VectorAlgorithmsImpl.dotProductF_VectorAPI_reduction_after_loop(a, b); @@ -425,7 +425,7 @@ public class TestVectorAlgorithms { IRNode.MUL_VI, IRNode.VECTOR_SIZE_8, "> 0", IRNode.ADD_VI, IRNode.VECTOR_SIZE_8, "> 0", IRNode.ADD_REDUCTION_VI, "> 0"}, - applyIfCPUFeatureOr = {"avx2", "true", "sve", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "sve", "true", "rvv", "true"}, applyIf = {"MaxVectorSize", ">=32"}) public int hashCodeB_VectorAPI_v1(byte[] a) { return VectorAlgorithmsImpl.hashCodeB_VectorAPI_v1(a); @@ -436,7 +436,7 @@ public class TestVectorAlgorithms { IRNode.MUL_VI, "> 0", IRNode.ADD_VI, "> 0", IRNode.ADD_REDUCTION_VI, "> 0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}) public int hashCodeB_VectorAPI_v2(byte[] a) { return VectorAlgorithmsImpl.hashCodeB_VectorAPI_v2(a); } @@ -445,7 +445,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.ADD_REDUCTION_VI, "> 0", IRNode.ADD_VI, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public int reduceAddI_VectorAPI_reduction_after_loop(int[] a) { return VectorAlgorithmsImpl.reduceAddI_VectorAPI_reduction_after_loop(a); } @@ -469,7 +469,7 @@ public class TestVectorAlgorithms { IRNode.AND_VI, "> 0", IRNode.ADD_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}, applyIf = {"MaxVectorSize", ">=64"}) public Object scanAddI_VectorAPI_permute_add(int[] a, int[] r) { return VectorAlgorithmsImpl.scanAddI_VectorAPI_permute_add(a, r); @@ -488,7 +488,7 @@ public class TestVectorAlgorithms { IRNode.VECTOR_BLEND_I, "> 0", IRNode.MIN_REDUCTION_V, "> 0", IRNode.ADD_VI, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) public int findMinIndexI_VectorAPI(int[] a) { return VectorAlgorithmsImpl.findMinIndexI_VectorAPI(a); } @@ -504,7 +504,7 @@ public class TestVectorAlgorithms { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.VECTOR_MASK_CMP, "> 0", IRNode.VECTOR_TEST, "> 0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) public int findI_VectorAPI(int[] a, int e) { return VectorAlgorithmsImpl.findI_VectorAPI(a, e); } @@ -522,7 +522,7 @@ public class TestVectorAlgorithms { IRNode.REARRANGE_VI, "> 0", IRNode.AND_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public Object reverseI_VectorAPI(int[] a, int[] r) { return VectorAlgorithmsImpl.reverseI_VectorAPI(a, r); } @@ -540,7 +540,7 @@ public class TestVectorAlgorithms { IRNode.VECTOR_TEST, "> 0", IRNode.COMPRESS_VI, "> 0", IRNode.STORE_VECTOR_MASKED, "> 0"}, - applyIfCPUFeatureOr = {"avx2", "true", "sve", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "sve", "true", "rvv", "true"}) public Object filterI_VectorAPI_v1(int[] a, int[] r, int threshold) { return VectorAlgorithmsImpl.filterI_VectorAPI_v1(a, r, threshold); } @@ -597,7 +597,7 @@ public class TestVectorAlgorithms { IRNode.OR_V_MASK, "> 0", IRNode.ADD_VI, "> 0", IRNode.ADD_REDUCTION_VI, "> 0"}, - applyIfCPUFeatureOr = {"avx512", "true", "sve", "true"}, + applyIfCPUFeatureOr = {"avx512", "true", "sve", "true", "rvv", "true"}, applyIf = {"TieredCompilation", "true"}) // IR check only works with TieredCompilation. Needs to make it // work with -XX:-TieredCompilation in future (see JDK-8378640). @@ -615,7 +615,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.ADD_VB, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public Object lowerCaseB_VectorAPI_v1(byte[] a, byte[] r) { return VectorAlgorithmsImpl.lowerCaseB_VectorAPI_v1(a, r); } @@ -623,7 +623,7 @@ public class TestVectorAlgorithms { @Test @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.ADD_VB, "> 0"}, - applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true", "rvv", "true"}) public Object lowerCaseB_VectorAPI_v2(byte[] a, byte[] r) { return VectorAlgorithmsImpl.lowerCaseB_VectorAPI_v2(a, r); } From 61a9c719835d46bcb447bb6855fe5bad12b77cf2 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Tue, 10 Mar 2026 09:35:35 +0000 Subject: [PATCH 137/170] 8379180: C2: assert((ptr->bottom_type() == Type::TOP) || ((base == Compile::current()->top()) == (ptr->bottom_type()->make_ptr()->isa_oopptr() == nullptr))) failed: base input only needed for heap addresses Reviewed-by: qamai, chagedorn --- src/hotspot/share/opto/macro.cpp | 94 +++++++++---------- .../c2/TestAllocatePrefetchStyle.java | 44 +++++++++ 2 files changed, 91 insertions(+), 47 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestAllocatePrefetchStyle.java diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index ef38a511a88..510531c95cd 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -1818,81 +1818,81 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, Node* old_eden_top, Node* new_eden_top, intx lines) { enum { fall_in_path = 1, pf_path = 2 }; - if( UseTLAB && AllocatePrefetchStyle == 2 ) { + if (UseTLAB && AllocatePrefetchStyle == 2) { // Generate prefetch allocation with watermark check. // As an allocation hits the watermark, we will prefetch starting // at a "distance" away from watermark. - Node *pf_region = new RegionNode(3); - Node *pf_phi_rawmem = new PhiNode( pf_region, Type::MEMORY, - TypeRawPtr::BOTTOM ); + Node* pf_region = new RegionNode(3); + Node* pf_phi_rawmem = new PhiNode(pf_region, Type::MEMORY, + TypeRawPtr::BOTTOM); // I/O is used for Prefetch - Node *pf_phi_abio = new PhiNode( pf_region, Type::ABIO ); + Node* pf_phi_abio = new PhiNode(pf_region, Type::ABIO); - Node *thread = new ThreadLocalNode(); + Node* thread = new ThreadLocalNode(); transform_later(thread); - Node *eden_pf_adr = new AddPNode( top()/*not oop*/, thread, - _igvn.MakeConX(in_bytes(JavaThread::tlab_pf_top_offset())) ); + Node* eden_pf_adr = new AddPNode(top()/*not oop*/, thread, + _igvn.MakeConX(in_bytes(JavaThread::tlab_pf_top_offset()))); transform_later(eden_pf_adr); - Node *old_pf_wm = new LoadPNode(needgc_false, + Node* old_pf_wm = new LoadPNode(needgc_false, contended_phi_rawmem, eden_pf_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered); transform_later(old_pf_wm); // check against new_eden_top - Node *need_pf_cmp = new CmpPNode( new_eden_top, old_pf_wm ); + Node* need_pf_cmp = new CmpPNode(new_eden_top, old_pf_wm); transform_later(need_pf_cmp); - Node *need_pf_bol = new BoolNode( need_pf_cmp, BoolTest::ge ); + Node* need_pf_bol = new BoolNode(need_pf_cmp, BoolTest::ge); transform_later(need_pf_bol); - IfNode *need_pf_iff = new IfNode( needgc_false, need_pf_bol, - PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN ); + IfNode* need_pf_iff = new IfNode(needgc_false, need_pf_bol, + PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN); transform_later(need_pf_iff); // true node, add prefetchdistance - Node *need_pf_true = new IfTrueNode( need_pf_iff ); + Node* need_pf_true = new IfTrueNode(need_pf_iff); transform_later(need_pf_true); - Node *need_pf_false = new IfFalseNode( need_pf_iff ); + Node* need_pf_false = new IfFalseNode(need_pf_iff); transform_later(need_pf_false); - Node *new_pf_wmt = new AddPNode( top(), old_pf_wm, - _igvn.MakeConX(AllocatePrefetchDistance) ); - transform_later(new_pf_wmt ); + Node* new_pf_wmt = new AddPNode(top(), old_pf_wm, + _igvn.MakeConX(AllocatePrefetchDistance)); + transform_later(new_pf_wmt); new_pf_wmt->set_req(0, need_pf_true); - Node *store_new_wmt = new StorePNode(need_pf_true, + Node* store_new_wmt = new StorePNode(need_pf_true, contended_phi_rawmem, eden_pf_adr, TypeRawPtr::BOTTOM, new_pf_wmt, MemNode::unordered); transform_later(store_new_wmt); // adding prefetches - pf_phi_abio->init_req( fall_in_path, i_o ); + pf_phi_abio->init_req(fall_in_path, i_o); - Node *prefetch_adr; - Node *prefetch; + Node* prefetch_adr; + Node* prefetch; uint step_size = AllocatePrefetchStepSize; uint distance = 0; - for ( intx i = 0; i < lines; i++ ) { - prefetch_adr = new AddPNode( old_pf_wm, new_pf_wmt, - _igvn.MakeConX(distance) ); + for (intx i = 0; i < lines; i++) { + prefetch_adr = new AddPNode(top(), new_pf_wmt, + _igvn.MakeConX(distance)); transform_later(prefetch_adr); - prefetch = new PrefetchAllocationNode( i_o, prefetch_adr ); + prefetch = new PrefetchAllocationNode(i_o, prefetch_adr); transform_later(prefetch); distance += step_size; i_o = prefetch; } - pf_phi_abio->set_req( pf_path, i_o ); + pf_phi_abio->set_req(pf_path, i_o); - pf_region->init_req( fall_in_path, need_pf_false ); - pf_region->init_req( pf_path, need_pf_true ); + pf_region->init_req(fall_in_path, need_pf_false); + pf_region->init_req(pf_path, need_pf_true); - pf_phi_rawmem->init_req( fall_in_path, contended_phi_rawmem ); - pf_phi_rawmem->init_req( pf_path, store_new_wmt ); + pf_phi_rawmem->init_req(fall_in_path, contended_phi_rawmem); + pf_phi_rawmem->init_req(pf_path, store_new_wmt); transform_later(pf_region); transform_later(pf_phi_rawmem); @@ -1901,7 +1901,7 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, needgc_false = pf_region; contended_phi_rawmem = pf_phi_rawmem; i_o = pf_phi_abio; - } else if( UseTLAB && AllocatePrefetchStyle == 3 ) { + } else if (UseTLAB && AllocatePrefetchStyle == 3) { // Insert a prefetch instruction for each allocation. // This code is used to generate 1 prefetch instruction per cache line. @@ -1910,7 +1910,7 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, uint distance = AllocatePrefetchDistance; // Next cache address. - Node *cache_adr = new AddPNode(old_eden_top, old_eden_top, + Node* cache_adr = new AddPNode(top(), old_eden_top, _igvn.MakeConX(step_size + distance)); transform_later(cache_adr); cache_adr = new CastP2XNode(needgc_false, cache_adr); @@ -1924,36 +1924,36 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false, transform_later(cache_adr); // Prefetch - Node *prefetch = new PrefetchAllocationNode( contended_phi_rawmem, cache_adr ); + Node* prefetch = new PrefetchAllocationNode(contended_phi_rawmem, cache_adr); prefetch->set_req(0, needgc_false); transform_later(prefetch); contended_phi_rawmem = prefetch; - Node *prefetch_adr; + Node* prefetch_adr; distance = step_size; - for ( intx i = 1; i < lines; i++ ) { - prefetch_adr = new AddPNode( cache_adr, cache_adr, - _igvn.MakeConX(distance) ); + for (intx i = 1; i < lines; i++) { + prefetch_adr = new AddPNode(top(), cache_adr, + _igvn.MakeConX(distance)); transform_later(prefetch_adr); - prefetch = new PrefetchAllocationNode( contended_phi_rawmem, prefetch_adr ); + prefetch = new PrefetchAllocationNode(contended_phi_rawmem, prefetch_adr); transform_later(prefetch); distance += step_size; contended_phi_rawmem = prefetch; } - } else if( AllocatePrefetchStyle > 0 ) { + } else if (AllocatePrefetchStyle > 0) { // Insert a prefetch for each allocation only on the fast-path - Node *prefetch_adr; - Node *prefetch; + Node* prefetch_adr; + Node* prefetch; // Generate several prefetch instructions. uint step_size = AllocatePrefetchStepSize; uint distance = AllocatePrefetchDistance; - for ( intx i = 0; i < lines; i++ ) { - prefetch_adr = new AddPNode( top(), new_eden_top, - _igvn.MakeConX(distance) ); + for (intx i = 0; i < lines; i++) { + prefetch_adr = new AddPNode(top(), new_eden_top, + _igvn.MakeConX(distance)); transform_later(prefetch_adr); - prefetch = new PrefetchAllocationNode( i_o, prefetch_adr ); + prefetch = new PrefetchAllocationNode(i_o, prefetch_adr); // Do not let it float too high, since if eden_top == eden_end, // both might be null. - if( i == 0 ) { // Set control for first prefetch, next follows it + if (i == 0) { // Set control for first prefetch, next follows it prefetch->init_req(0, needgc_false); } transform_later(prefetch); diff --git a/test/hotspot/jtreg/compiler/c2/TestAllocatePrefetchStyle.java b/test/hotspot/jtreg/compiler/c2/TestAllocatePrefetchStyle.java new file mode 100644 index 00000000000..53763302f90 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestAllocatePrefetchStyle.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2026 IBM Corporation. All rights reserved. + * 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 8379180 + * @summary test AllocatePrefetchStyle + * + * @run main/othervm -Xbatch -XX:AllocatePrefetchStyle=2 compiler.c2.TestAllocatePrefetchStyle + * @run main/othervm -Xbatch -XX:AllocatePrefetchStyle=3 compiler.c2.TestAllocatePrefetchStyle + */ +package compiler.c2; + +public class TestAllocatePrefetchStyle { + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + + private static int[] test() { + return new int[10]; + } +} From ce7a890fb434d15da51dd7e21847c4a4bbabf99f Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 10 Mar 2026 10:16:29 +0000 Subject: [PATCH 138/170] 8379200: G1: Remove G1HeapRegion completion facility Reviewed-by: ayang, iwalulya --- src/hotspot/share/gc/g1/g1CollectionSet.cpp | 3 +-- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 5 ---- src/hotspot/share/gc/g1/g1HeapRegion.hpp | 26 ------------------- .../share/gc/g1/g1HeapRegionManager.cpp | 2 -- 4 files changed, 1 insertion(+), 35 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.cpp b/src/hotspot/share/gc/g1/g1CollectionSet.cpp index abfddf860e6..39acaaab913 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -174,7 +174,6 @@ void G1CollectionSet::iterate(G1HeapRegionClosure* cl) const { G1HeapRegion* r = _g1h->region_at(_regions[i]); bool result = cl->do_heap_region(r); if (result) { - cl->set_incomplete(); return; } } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index b4a5d673fd2..a2114d8d6b6 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -817,10 +817,6 @@ public: SuspendibleThreadSetJoiner sts_join(_suspendible); G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&_cl, &_hr_claimer, worker_id); } - - bool is_complete() { - return _cl.is_complete(); - } }; void G1ConcurrentMark::clear_bitmap(WorkerThreads* workers, bool may_yield) { @@ -835,7 +831,6 @@ void G1ConcurrentMark::clear_bitmap(WorkerThreads* workers, bool may_yield) { log_debug(gc, ergo)("Running %s with %u workers for %zu work units.", cl.name(), num_workers, num_chunks); workers->run_task(&cl, num_workers); - guarantee(may_yield || cl.is_complete(), "Must have completed iteration when not yielding."); } void G1ConcurrentMark::cleanup_for_next_mark() { diff --git a/src/hotspot/share/gc/g1/g1HeapRegion.hpp b/src/hotspot/share/gc/g1/g1HeapRegion.hpp index 2b4b640d52b..ec9cab26049 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegion.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegion.hpp @@ -567,41 +567,15 @@ public: // G1HeapRegionClosure is used for iterating over regions. // Terminates the iteration when the "do_heap_region" method returns "true". class G1HeapRegionClosure : public StackObj { - friend class G1HeapRegionManager; - friend class G1CollectionSet; - friend class G1CollectionSetCandidates; - - bool _is_complete; - void set_incomplete() { _is_complete = false; } - public: - G1HeapRegionClosure(): _is_complete(true) {} - // Typically called on each region until it returns true. virtual bool do_heap_region(G1HeapRegion* r) = 0; - - // True after iteration if the closure was applied to all heap regions - // and returned "false" in all cases. - bool is_complete() { return _is_complete; } }; class G1HeapRegionIndexClosure : public StackObj { - friend class G1HeapRegionManager; - friend class G1CollectionSet; - friend class G1CollectionSetCandidates; - - bool _is_complete; - void set_incomplete() { _is_complete = false; } - public: - G1HeapRegionIndexClosure(): _is_complete(true) {} - // Typically called on each region until it returns true. virtual bool do_heap_region_index(uint region_index) = 0; - - // True after iteration if the closure was applied to all heap regions - // and returned "false" in all cases. - bool is_complete() { return _is_complete; } }; #endif // SHARE_GC_G1_G1HEAPREGION_HPP diff --git a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp index fdd3b919590..3c0318827ef 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp @@ -511,7 +511,6 @@ void G1HeapRegionManager::iterate(G1HeapRegionClosure* blk) const { guarantee(at(i) != nullptr, "Tried to access region %u that has a null G1HeapRegion*", i); bool res = blk->do_heap_region(at(i)); if (res) { - blk->set_incomplete(); return; } } @@ -526,7 +525,6 @@ void G1HeapRegionManager::iterate(G1HeapRegionIndexClosure* blk) const { } bool res = blk->do_heap_region_index(i); if (res) { - blk->set_incomplete(); return; } } From 66e192c6005fccaba07fbb41393ddd16fc9fad30 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Tue, 10 Mar 2026 12:20:28 +0000 Subject: [PATCH 139/170] 8377602: Create automated test for PageRange Reviewed-by: prr, psadhukhan, dmarkov --- .../awt/print/PrinterJob/PageRangesAuto.java | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 test/jdk/java/awt/print/PrinterJob/PageRangesAuto.java diff --git a/test/jdk/java/awt/print/PrinterJob/PageRangesAuto.java b/test/jdk/java/awt/print/PrinterJob/PageRangesAuto.java new file mode 100644 index 00000000000..8d50ef9c2c2 --- /dev/null +++ b/test/jdk/java/awt/print/PrinterJob/PageRangesAuto.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2007, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Font; +import java.awt.Graphics; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.List; +import java.util.stream.IntStream; + +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Destination; +import javax.print.attribute.standard.PageRanges; + +/* + * @test + * @bug 6575331 8297191 + * @key printer + * @summary Automatically verifies all the pages in a range are printed + * @run main PageRangesAuto + */ +public class PageRangesAuto implements Pageable, Printable { + + private static final Font font = new Font(Font.SERIF, Font.PLAIN, 50); + + private static final int MAX_PAGE = 10; + + private static final int[][] ranges = { + {1, 1}, + {1, MAX_PAGE}, + {2, 3}, + {3, 6}, + {4, 7}, + {7, 7}, + {9, MAX_PAGE}, + {MAX_PAGE, MAX_PAGE}, + }; + + private enum Type { + PRINTABLE, + PAGEABLE + } + + private final BitSet printedPages = new BitSet(); + + /** + * Configures a printer job and prints it. + * @param type the type of the interface tested + * ({@code Printable} or {@code Pageable}) + * @param pageRange the range of pages to print; + * if {@code null}, print all pages + * @return a bit set of printed page numbers + */ + private static BitSet printJob(final Type type, + final PageRanges pageRange) + throws PrinterException { + final PageRangesAuto test = new PageRangesAuto(); + + final PrinterJob job = PrinterJob.getPrinterJob(); + final String baseName = type.name().toLowerCase(); + + switch (type) { + case PRINTABLE -> job.setPrintable(test); + case PAGEABLE -> job.setPageable(test); + } + + String fileName = pageRange == null + ? baseName + "-all.pdf" + : String.format("%s-%d-%d.pdf", + baseName, + pageRange.getMembers()[0][0], + pageRange.getMembers()[0][1]); + + PrintRequestAttributeSet set = new HashPrintRequestAttributeSet(); + set.add(new Destination(new File(fileName) + .toURI())); + if (pageRange != null) { + set.add(pageRange); + } + + job.print(set); + + return test.printedPages; + } + + public static void main(String[] args) throws Exception { + final List errors = new ArrayList<>(); + + for (Type type : Type.values()) { + BitSet pages; // Printed pages + + // Print all pages + System.out.println(type + " - all pages"); + pages = printJob(type, null); + if (!IntStream.range(0, MAX_PAGE) + .allMatch(pages::get)) { + errors.add(new Error("Not all pages printed in " + type + ": " + + pages)); + } + + // Print page range + for (int[] range : ranges) { + System.out.println(type + " - " + Arrays.toString(range)); + pages = printJob(type, new PageRanges(range[0], range[1])); + if (!IntStream.range(range[0] - 1, range[1]) + .allMatch(pages::get)) { + errors.add(new Error("Not all pages printed in " + type + + " within the range " + + Arrays.toString(range) + + ": " + pages)); + } + } + } + + if (!errors.isEmpty()) { + errors.forEach(System.err::println); + throw new RuntimeException("Errors detected: " + errors.size() + + ". - " + errors.getFirst()); + } + } + + @Override + public int print(Graphics g, PageFormat format, int pageIndex) + throws PrinterException { + printedPages.set(pageIndex); + + final int pageNo = pageIndex + 1; + System.out.println(" test.printPage " + pageNo); + if (pageIndex >= MAX_PAGE) { + return NO_SUCH_PAGE; + } + + g.setFont(font); + g.drawString("Page: " + pageNo, + 100, 150); + + return PAGE_EXISTS; + } + + @Override + public int getNumberOfPages() { + System.out.println(" test.getNumberOfPages = " + MAX_PAGE); + return MAX_PAGE; + } + + @Override + public PageFormat getPageFormat(int pageIndex) + throws IndexOutOfBoundsException { + checkPageIndex(pageIndex); + return new PageFormat(); + } + + @Override + public Printable getPrintable(int pageIndex) + throws IndexOutOfBoundsException { + checkPageIndex(pageIndex); + System.out.println(" test.getPrintable(" + (pageIndex + 1) + ")"); + return this; + } + + private static void checkPageIndex(int pageIndex) + throws IndexOutOfBoundsException { + if (pageIndex < 0) { + throw new IndexOutOfBoundsException("pageIndex < 0"); + } + + if (pageIndex >= MAX_PAGE) { + throw new IndexOutOfBoundsException("pageIndex >= " + MAX_PAGE); + } + } +} From 6aae92e6f13f5964270c6ce5b54a14e98c1b6fe1 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Tue, 10 Mar 2026 12:23:06 +0000 Subject: [PATCH 140/170] 8379564: Hotspot fails to build with gcc 14 after JDK-8378804 Reviewed-by: ysuenaga, stuefe --- src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp index 42db0b2fd2c..dbae1b35c6f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2024, Red Hat, Inc. All rights reserved. - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -320,7 +320,7 @@ public: DEBUG_ONLY(_reserved = 0; ) } - void clear_claimed() { _claimed_index = 0; } + void clear_claimed() { _claimed_index.store_relaxed(0); } T* claim_next(); // reserve queues that not for parallel claiming From f95e8136b1f69d2c263d0126dcbc9dbc0a485352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Tue, 10 Mar 2026 12:37:39 +0000 Subject: [PATCH 141/170] 8379412: JfrJavaSupport::new_string should return early if pending exception Reviewed-by: mgronlun --- src/hotspot/share/jfr/jni/jfrJavaSupport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp index 59a9d8a9090..a6e97ab227a 100644 --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp @@ -228,7 +228,7 @@ void JfrJavaSupport::new_object_global_ref(JfrJavaArguments* args, TRAPS) { jstring JfrJavaSupport::new_string(const char* c_str, TRAPS) { assert(c_str != nullptr, "invariant"); DEBUG_ONLY(check_java_thread_in_vm(THREAD)); - const oop result = java_lang_String::create_oop_from_str(c_str, THREAD); + const oop result = java_lang_String::create_oop_from_str(c_str, CHECK_NULL); return (jstring)local_jni_handle(result, THREAD); } From bad59c55d98b2ef3b4a810e767577093b44764cd Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 10 Mar 2026 13:05:11 +0000 Subject: [PATCH 142/170] 8379437: Refactor ProcessBuilder and ProcessHandle tests to JUnit Reviewed-by: jpai --- .../lang/ProcessBuilder/InheritIOTest.java | 36 +++--- .../lang/ProcessBuilder/ProcessReaperCCL.java | 17 ++- .../ProcessStartLoggingTest.java | 5 +- .../lang/ProcessBuilder/ReaderWriterTest.java | 116 +++++++----------- test/jdk/java/lang/ProcessHandle/Basic.java | 61 ++++----- .../jdk/java/lang/ProcessHandle/InfoTest.java | 94 +++++++------- .../java/lang/ProcessHandle/OnExitTest.java | 64 ++++------ .../jdk/java/lang/ProcessHandle/TreeTest.java | 109 ++++++++-------- 8 files changed, 215 insertions(+), 287 deletions(-) diff --git a/test/jdk/java/lang/ProcessBuilder/InheritIOTest.java b/test/jdk/java/lang/ProcessBuilder/InheritIOTest.java index a372eeefbf8..b3f52663a59 100644 --- a/test/jdk/java/lang/ProcessBuilder/InheritIOTest.java +++ b/test/jdk/java/lang/ProcessBuilder/InheritIOTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,22 @@ /* * @test - * @bug 8023130 8166026 * @summary Unit test for java.lang.ProcessBuilder inheritance of standard output and standard error streams + * @bug 8023130 8166026 * @requires vm.flagless * @library /test/lib * @build jdk.test.lib.process.* - * @run testng InheritIOTest + * @run junit InheritIOTest */ import java.util.List; import static java.lang.ProcessBuilder.Redirect.INHERIT; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; public class InheritIOTest { @@ -45,25 +46,25 @@ public class InheritIOTest { private static final String EXPECTED_RESULT_STDOUT = "message"; private static final String EXPECTED_RESULT_STDERR = EXIT_VALUE_TEMPLATE.formatted(0); - @DataProvider - public Object[][] testCases() { - return new Object[][]{ - new Object[] { List.of("InheritIOTest$TestInheritIO", "printf", EXPECTED_RESULT_STDOUT) }, - new Object[] { List.of("InheritIOTest$TestRedirectInherit", "printf", EXPECTED_RESULT_STDOUT) } - }; + public static List testCases() { + return List.of( + Arguments.of(List.of("InheritIOTest$TestInheritIO", "printf", EXPECTED_RESULT_STDOUT)), + Arguments.of(List.of("InheritIOTest$TestRedirectInherit", "printf", EXPECTED_RESULT_STDOUT)) + ); } - @Test(dataProvider = "testCases") + @ParameterizedTest + @MethodSource("testCases") public void testInheritWithoutRedirect(List arguments) throws Throwable { ProcessBuilder processBuilder = ProcessTools.createLimitedTestJavaProcessBuilder(arguments); OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(processBuilder); outputAnalyzer.shouldHaveExitValue(0); - assertEquals(outputAnalyzer.getStdout(), EXPECTED_RESULT_STDOUT); - assertEquals(outputAnalyzer.getStderr(), EXPECTED_RESULT_STDERR); + assertEquals(EXPECTED_RESULT_STDOUT, outputAnalyzer.getStdout()); + assertEquals(EXPECTED_RESULT_STDERR, outputAnalyzer.getStderr()); } public static class TestInheritIO { - public static void main(String args[]) throws Throwable { + public static void main(String[] args) throws Throwable { int err = new ProcessBuilder(args).inheritIO().start().waitFor(); System.err.printf(EXIT_VALUE_TEMPLATE, err); System.exit(err); @@ -71,7 +72,7 @@ public class InheritIOTest { } public static class TestRedirectInherit { - public static void main(String args[]) throws Throwable { + public static void main(String[] args) throws Throwable { int err = new ProcessBuilder(args) .redirectInput(INHERIT) .redirectOutput(INHERIT) @@ -81,5 +82,4 @@ public class InheritIOTest { System.exit(err); } } - } diff --git a/test/jdk/java/lang/ProcessBuilder/ProcessReaperCCL.java b/test/jdk/java/lang/ProcessBuilder/ProcessReaperCCL.java index 79593b014c3..605441cb996 100644 --- a/test/jdk/java/lang/ProcessBuilder/ProcessReaperCCL.java +++ b/test/jdk/java/lang/ProcessBuilder/ProcessReaperCCL.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,9 @@ /* * @test - * @bug 8269488 * @summary verify that Process Reaper threads have a null CCL - * @run testng ProcessReaperCCL + * @bug 8269488 + * @run junit ProcessReaperCCL */ import java.io.File; @@ -34,14 +34,13 @@ import java.net.URLClassLoader; import java.util.List; import java.util.concurrent.CompletableFuture; -import org.testng.Assert; -import org.testng.annotations.Test; - +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class ProcessReaperCCL { @Test - static void test() throws Exception { + void test() throws Exception { // create a class loader File dir = new File("."); URL[] urls = new URL[] {dir.toURI().toURL()}; @@ -53,12 +52,12 @@ public class ProcessReaperCCL { Process p = pb.start(); CompletableFuture cf = p.onExit(); int exitValue = cf.get().exitValue(); - Assert.assertEquals(exitValue, 0, "error exit value"); + Assertions.assertEquals(0, exitValue, "error exit value"); // Verify all "Process Reaper" threads have a null CCL for (Thread th : Thread.getAllStackTraces().keySet()) { if (th.getName().startsWith("process reaper")) { - Assert.assertEquals(th.getContextClassLoader(), null, "CCL not null"); + Assertions.assertNull(th.getContextClassLoader(), "CCL not null"); } } } diff --git a/test/jdk/java/lang/ProcessBuilder/ProcessStartLoggingTest.java b/test/jdk/java/lang/ProcessBuilder/ProcessStartLoggingTest.java index e9b2fa6b264..2f2bc3c3cee 100644 --- a/test/jdk/java/lang/ProcessBuilder/ProcessStartLoggingTest.java +++ b/test/jdk/java/lang/ProcessBuilder/ProcessStartLoggingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,7 @@ import java.util.stream.Stream; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.ParameterizedTest; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.*; /* * @test diff --git a/test/jdk/java/lang/ProcessBuilder/ReaderWriterTest.java b/test/jdk/java/lang/ProcessBuilder/ReaderWriterTest.java index a73451417bf..6bff8d5e592 100644 --- a/test/jdk/java/lang/ProcessBuilder/ReaderWriterTest.java +++ b/test/jdk/java/lang/ProcessBuilder/ReaderWriterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,17 +21,10 @@ * questions. */ -import static org.testng.Assert.*; - -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.*; import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.hexdump.HexPrinter; -import jdk.test.lib.hexdump.HexPrinter.Formatters; - import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; @@ -42,20 +35,23 @@ import java.nio.file.Files; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; -import java.util.List; -import java.util.Locale; +import java.util.stream.Stream; import jtreg.SkippedException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; /* * @test * @requires vm.flagless * @library /test/lib - * @build jdk.test.lib.process.ProcessTools jdk.test.lib.hexdump.HexPrinter - * @run testng ReaderWriterTest + * @build jdk.test.lib.process.ProcessTools + * @run junit ReaderWriterTest */ -@Test public class ReaderWriterTest { static final String ASCII = "ASCII: \u0000_A-Z_a-Z_\u007C_\u007D_\u007E_\u007F_;"; @@ -65,13 +61,12 @@ public class ReaderWriterTest { public static final String TESTCHARS = "OneWay: " + ASCII + ISO_8859_1 + FRACTIONS; public static final String ROUND_TRIP_TESTCHARS = "RoundTrip: " + ASCII + ISO_8859_1 + FRACTIONS; - @DataProvider(name="CharsetCases") - static Object[][] charsetCases() { - return new Object[][] { - {"UTF-8"}, - {"ISO8859-1"}, - {"US-ASCII"}, - }; + static Stream charsetCases() { + return Stream.of( + Arguments.of("UTF-8"), + Arguments.of("ISO8859-1"), + Arguments.of("US-ASCII") + ); } /** @@ -93,7 +88,7 @@ public class ReaderWriterTest { if (exitValue != 0) System.out.println("exitValue: " + exitValue); } catch (InterruptedException ie) { - Assert.fail("waitFor interrupted"); + fail("waitFor interrupted"); } } @@ -131,32 +126,28 @@ public class ReaderWriterTest { if (errType == 2 || errType == 3) { pb.redirectErrorStream(true); } - Process p = pb.start(); - // Output has been redirected to a null stream; success is IOException on the write - try { + try (Process p = pb.start()) { + // Output has been redirected to a null stream; success is IOException on the write BufferedWriter wr = p.outputWriter(); - wr.write("X"); - wr.flush(); - Assert.fail("writing to null stream should throw IOException"); - } catch (IOException ioe) { - // Normal, A Null output stream is closed when created. - } + assertThrows(IOException.class, () -> { + wr.write("X"); + wr.flush(); + }); - // InputReader should be empty; and at EOF - BufferedReader inputReader = p.inputReader(); - int ch = inputReader.read(); - Assert.assertEquals(ch, -1, "inputReader not at EOF: ch: " + (char)ch); + // InputReader should be empty; and at EOF + BufferedReader inputReader = p.inputReader(); + int ch = inputReader.read(); + assertEquals(-1, ch, "inputReader not at EOF: ch: " + (char) ch); - // InputReader should be empty; and at EOF - BufferedReader errorReader = p.errorReader(); - ch = errorReader.read(); - Assert.assertEquals(ch, -1, "errorReader not at EOF: ch: " + (char)ch); + // InputReader should be empty; and at EOF + BufferedReader errorReader = p.errorReader(); + ch = errorReader.read(); + assertEquals(-1, ch, "errorReader not at EOF: ch: " + (char) ch); - try { int exitValue = p.waitFor(); if (exitValue != 0) System.out.println("exitValue: " + exitValue); } catch (InterruptedException ie) { - Assert.fail("waitFor interrupted"); + fail("waitFor interrupted"); } } } @@ -181,7 +172,8 @@ public class ReaderWriterTest { * * @param encoding a charset name */ - @Test(dataProvider = "CharsetCases", enabled = true) + @ParameterizedTest + @MethodSource("charsetCases") void testCase(String encoding) throws IOException { Charset cs = null; try { @@ -221,32 +213,10 @@ public class ReaderWriterTest { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( "ReaderWriterTest$ChildWithCharset"); - Process p = pb.start(); - try { - writeTestChars(p.outputWriter(null)); - Assert.fail("Process.outputWriter(null) did not throw NPE"); - } catch (NullPointerException npe) { - // expected, ignore - } - try { - checkReader(p.inputReader(null), null, "Out"); - Assert.fail("Process.inputReader(null) did not throw NPE"); - } catch (NullPointerException npe) { - // expected, ignore - } - try { - checkReader(p.errorReader(null), null, "Err"); - Assert.fail("Process.errorReader(null) did not throw NPE"); - } catch (NullPointerException npe) { - // expected, ignore - } - - p.destroyForcibly(); - try { - // Collect the exit status to cleanup after the process; but ignore it - p.waitFor(); - } catch (InterruptedException ie) { - // Ignored + try (Process p = pb.start()) { + assertThrows(NullPointerException.class, () -> writeTestChars(p.outputWriter(null))); + assertThrows(NullPointerException.class, () -> checkReader(p.inputReader(null), null, "Out")); + assertThrows(NullPointerException.class, () -> checkReader(p.errorReader(null), null, "Err")); } } @@ -272,7 +242,7 @@ public class ReaderWriterTest { var writer = p.outputWriter(cs); writer = p.outputWriter(cs); // try again with same writer = p.outputWriter(otherCharset); // this should throw - Assert.fail("Process.outputWriter(otherCharset) did not throw IllegalStateException"); + fail("Process.outputWriter(otherCharset) did not throw IllegalStateException"); } catch (IllegalStateException ile) { // expected, ignore System.out.println(ile); @@ -281,7 +251,7 @@ public class ReaderWriterTest { var reader = p.inputReader(cs); reader = p.inputReader(cs); // try again with same reader = p.inputReader(otherCharset); // this should throw - Assert.fail("Process.inputReader(otherCharset) did not throw IllegalStateException"); + fail("Process.inputReader(otherCharset) did not throw IllegalStateException"); } catch (IllegalStateException ile) { // expected, ignore System.out.println(ile); @@ -290,7 +260,7 @@ public class ReaderWriterTest { var reader = p.errorReader(cs); reader = p.errorReader(cs); // try again with same reader = p.errorReader(otherCharset); // this should throw - Assert.fail("Process.errorReader(otherCharset) did not throw IllegalStateException"); + fail("Process.errorReader(otherCharset) did not throw IllegalStateException"); } catch (IllegalStateException ile) { // expected, ignore System.out.println(ile); @@ -320,13 +290,13 @@ public class ReaderWriterTest { String reencoded = cs.decode(bb).toString(); if (!firstline.equals(reencoded)) diffStrings(firstline, reencoded); - assertEquals(firstline, reencoded, label + " Test Chars"); + assertEquals(reencoded, firstline, label + " Test Chars"); bb = cs.encode(ROUND_TRIP_TESTCHARS); reencoded = cs.decode(bb).toString(); if (!secondline.equals(reencoded)) diffStrings(secondline, reencoded); - assertEquals(secondline, reencoded, label + " Round Trip Test Chars"); + assertEquals(reencoded, secondline, label + " Round Trip Test Chars"); } } diff --git a/test/jdk/java/lang/ProcessHandle/Basic.java b/test/jdk/java/lang/ProcessHandle/Basic.java index 09674814283..d0342b35a23 100644 --- a/test/jdk/java/lang/ProcessHandle/Basic.java +++ b/test/jdk/java/lang/ProcessHandle/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,21 +21,22 @@ * questions. */ -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import org.testng.TestNG; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /* * @test + * @summary Basic tests for ProcessHandler * @library /test/lib * @modules java.base/jdk.internal.misc * jdk.management @@ -45,20 +46,18 @@ import org.testng.annotations.Test; * jdk.test.lib.JDKToolLauncher * jdk.test.lib.Platform * jdk.test.lib.process.* - * @run testng Basic - * @summary Basic tests for ProcessHandler - * @author Roger Riggs + * @run junit Basic */ public class Basic { /** * Tests of ProcessHandle.current. */ @Test - public static void test1() { + public void test1() { try { ProcessHandle self = ProcessHandle.current(); ProcessHandle self1 = ProcessHandle.current(); - assertEquals(self, self1); //, "get pid twice should be same %d: %d"); + assertEquals(self1, self); //, "get pid twice should be same %d: %d"); } finally { // Cleanup any left over processes ProcessHandle.current().children().forEach(ProcessHandle::destroy); @@ -69,16 +68,16 @@ public class Basic { * Tests of ProcessHandle.get. */ @Test - public static void test2() { + public void test2() { try { ProcessHandle self = ProcessHandle.current(); long pid = self.pid(); // known native process id Optional self1 = ProcessHandle.of(pid); - assertEquals(self1.get(), self, + assertEquals(self, self1.get(), "ProcessHandle.of(x.pid()) should be equal pid() %d: %d"); Optional ph = ProcessHandle.of(pid); - assertEquals(pid, ph.get().pid()); + assertEquals(ph.get().pid(), pid); } finally { // Cleanup any left over processes ProcessHandle.current().children().forEach(ProcessHandle::destroy); @@ -86,7 +85,7 @@ public class Basic { } @Test - public static void test3() { + public void test3() { // Test can get parent of current ProcessHandle ph = ProcessHandle.current(); try { @@ -99,7 +98,7 @@ public class Basic { } @Test - public static void test4() { + public void test4() { try { Process p = new ProcessBuilder("sleep", "0").start(); p.waitFor(); @@ -118,7 +117,7 @@ public class Basic { } @Test - public static void test5() { + public void test5() { // Always contains itself. ProcessHandle current = ProcessHandle.current(); List list = ProcessHandle.allProcesses().collect(Collectors.toList()); @@ -131,23 +130,17 @@ public class Basic { } } - @Test(expectedExceptions = IllegalStateException.class) - public static void test6() { - ProcessHandle.current().onExit(); + @Test + public void test6() { + Assertions.assertThrows(IllegalStateException.class, () -> { + ProcessHandle.current().onExit(); + }); } - @Test(expectedExceptions = IllegalStateException.class) - public static void test7() { - ProcessHandle.current().destroyForcibly(); + @Test + public void test7() { + Assertions.assertThrows(IllegalStateException.class, () -> { + ProcessHandle.current().destroyForcibly(); + }); } - - // Main can be used to run the tests from the command line with only testng.jar. - @SuppressWarnings("raw_types") - public static void main(String[] args) { - Class[] testclass = {TreeTest.class}; - TestNG testng = new TestNG(); - testng.setTestClasses(testclass); - testng.run(); - } - } diff --git a/test/jdk/java/lang/ProcessHandle/InfoTest.java b/test/jdk/java/lang/ProcessHandle/InfoTest.java index 38c86db3b91..ea2739e14a7 100644 --- a/test/jdk/java/lang/ProcessHandle/InfoTest.java +++ b/test/jdk/java/lang/ProcessHandle/InfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,15 +39,15 @@ import java.util.Optional; import java.util.Random; import java.util.concurrent.TimeUnit; -import org.testng.Assert; -import org.testng.TestNG; -import org.testng.annotations.Test; import jdk.test.lib.Platform; import jdk.test.lib.Utils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /* * @test + * @summary Functions of ProcessHandle.Info * @bug 8077350 8081566 8081567 8098852 8136597 * @requires os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*") * @library /test/lib @@ -59,8 +59,7 @@ import jdk.test.lib.Utils; * jdk.test.lib.JDKToolLauncher * jdk.test.lib.Platform * jdk.test.lib.process.* - * @run testng InfoTest - * @summary Functions of ProcessHandle.Info + * @run junit InfoTest * @author Roger Riggs */ @@ -82,19 +81,11 @@ public class InfoTest { } } - // Main can be used to run the tests from the command line with only testng.jar. - public static void main(String[] args) { - Class[] testclass = {InfoTest.class}; - TestNG testng = new TestNG(); - testng.setTestClasses(testclass); - testng.run(); - } - /** * Test that cputime used shows up in ProcessHandle.info */ @Test - public static void test1() { + public void test1() { System.out.println("Note: when run in samevm mode the cputime of the " + "test runner is included."); ProcessHandle self = ProcessHandle.current(); @@ -108,7 +99,7 @@ public class InfoTest { System.out.printf(" info: %s%n", info); Optional totalCpu = info.totalCpuDuration(); if (totalCpu.isPresent() && (totalCpu.get().compareTo(someCPU) < 0)) { - Assert.fail("reported cputime less than expected: " + someCPU + ", " + + Assertions.fail("reported cputime less than expected: " + someCPU + ", " + "actual: " + info.totalCpuDuration()); } } @@ -117,7 +108,7 @@ public class InfoTest { * Spawn a child with arguments and check they are visible via the ProcessHandle. */ @Test - public static void test2() { + public void test2() { try { long cpuLoopTime = 100; // 100 ms String[] extraArgs = {"pid", "parent", "stdin"}; @@ -170,7 +161,7 @@ public class InfoTest { String expected = Platform.isWindows() ? javaExe + ".exe" : javaExe; Path expectedPath = Paths.get(expected); Path actualPath = Paths.get(command.get()); - Assert.assertTrue(Files.isSameFile(expectedPath, actualPath), + Assertions.assertTrue(Files.isSameFile(expectedPath, actualPath), "Command: expected: " + javaExe + ", actual: " + command.get()); } @@ -179,22 +170,20 @@ public class InfoTest { int offset = args.length - extraArgs.length; for (int i = 0; i < extraArgs.length; i++) { - Assert.assertEquals(args[offset + i], extraArgs[i], + Assertions.assertEquals(extraArgs[i], args[offset + i], "Actual argument mismatch, index: " + i); } // Now check that the first argument is not the same as the executed command - if (args.length > 0) { - Assert.assertNotEquals(args[0], command, - "First argument should not be the executable: args[0]: " - + args[0] + ", command: " + command); - } + Assertions.assertNotEquals(command, args[0], + "First argument should not be the executable: args[0]: " + + args[0] + ", command: " + command); } if (command.isPresent() && info.arguments().isPresent()) { // If both, 'command' and 'arguments' are present, // 'commandLine' is just the concatenation of the two. - Assert.assertTrue(info.commandLine().isPresent(), + Assertions.assertTrue(info.commandLine().isPresent(), "commandLine() must be available"); String javaExe = System.getProperty("test.jdk") + @@ -204,15 +193,15 @@ public class InfoTest { String commandLine = info.commandLine().get(); String commandLineCmd = commandLine.split(" ")[0]; Path commandLineCmdPath = Paths.get(commandLineCmd); - Assert.assertTrue(Files.isSameFile(commandLineCmdPath, expectedPath), + Assertions.assertTrue(Files.isSameFile(commandLineCmdPath, expectedPath), "commandLine() should start with: " + expectedPath + " but starts with " + commandLineCmdPath); - Assert.assertTrue(commandLine.contains(command.get()), + Assertions.assertTrue(commandLine.contains(command.get()), "commandLine() must contain the command: " + command.get()); List allArgs = p1.getArgs(); for (int i = 1; i < allArgs.size(); i++) { - Assert.assertTrue(commandLine.contains(allArgs.get(i)), + Assertions.assertTrue(commandLine.contains(allArgs.get(i)), "commandLine() must contain argument: " + allArgs.get(i)); } } else if (info.commandLine().isPresent() && @@ -222,14 +211,14 @@ public class InfoTest { String commandLine = info.commandLine().get(); String javaExe = "java" + (Platform.isWindows() ? ".exe" : ""); int pos = commandLine.indexOf(javaExe); - Assert.assertTrue(pos > 0, "commandLine() should at least contain 'java'"); + Assertions.assertTrue(pos > 0, "commandLine() should at least contain 'java'"); pos += javaExe.length() + 1; // +1 for the space after the command List allArgs = p1.getArgs(); // First argument is the command - skip it here as we've already checked that. for (int i = 1; (i < allArgs.size()) && (pos + allArgs.get(i).length() < commandLine.length()); i++) { - Assert.assertTrue(commandLine.contains(allArgs.get(i)), + Assertions.assertTrue(commandLine.contains(allArgs.get(i)), "commandLine() must contain argument: " + allArgs.get(i)); pos += allArgs.get(i).length() + 1; } @@ -242,14 +231,14 @@ public class InfoTest { System.out.printf(" info.totalCPU: %s, childCpuTime: %s, diff: %s%n", totalCPU.toNanos(), childCpuTime.toNanos(), childCpuTime.toNanos() - totalCPU.toNanos()); - Assert.assertTrue(checkEpsilon(childCpuTime, totalCPU, epsilon), + Assertions.assertTrue(checkEpsilon(childCpuTime, totalCPU, epsilon), childCpuTime + " should be within " + epsilon + " of " + totalCPU); } - Assert.assertTrue(totalCPU.toNanos() > 0L, + Assertions.assertTrue(totalCPU.toNanos() > 0L, "total cpu time expected > 0ms, actual: " + totalCPU); long t = Utils.adjustTimeout(10L); // Adjusted timeout seconds - Assert.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + t * 1_000_000_000L, + Assertions.assertTrue(totalCPU.toNanos() < lastCpu.toNanos() + t * 1_000_000_000L, "total cpu time expected < " + t + " seconds more than previous iteration, actual: " + (totalCPU.toNanos() - lastCpu.toNanos())); @@ -258,18 +247,18 @@ public class InfoTest { if (info.startInstant().isPresent()) { Instant startTime = info.startInstant().get(); - Assert.assertTrue(startTime.isBefore(afterStart), + Assertions.assertTrue(startTime.isBefore(afterStart), "startTime after process spawn completed" + startTime + " + > " + afterStart); } } } p1.sendAction("exit"); - Assert.assertTrue(p1.waitFor(Utils.adjustTimeout(30L), TimeUnit.SECONDS), + Assertions.assertTrue(p1.waitFor(Utils.adjustTimeout(30L), TimeUnit.SECONDS), "timeout waiting for process to terminate"); } catch (IOException | InterruptedException ie) { ie.printStackTrace(System.out); - Assert.fail("unexpected exception", ie); + Assertions.fail("unexpected exception", ie); } finally { // Destroy any children that still exist ProcessUtil.destroyProcessTree(ProcessHandle.current()); @@ -280,7 +269,7 @@ public class InfoTest { * Spawn a child with arguments and check they are visible via the ProcessHandle. */ @Test - public static void test3() { + public void test3() { try { for (long sleepTime : Arrays.asList(Utils.adjustTimeout(30), Utils.adjustTimeout(32))) { Process p = spawn("sleep", String.valueOf(sleepTime)); @@ -302,22 +291,22 @@ public class InfoTest { Path executable = Files.readSymbolicLink(Paths.get("/bin/sleep")); expected = executable.getFileName().toString(); } - Assert.assertTrue(command.endsWith(expected), "Command: expected: \'" + + Assertions.assertTrue(command.endsWith(expected), "Command: expected: \'" + expected + "\', actual: " + command); // Verify the command exists and is executable File exe = new File(command); - Assert.assertTrue(exe.exists(), "command must exist: " + exe); - Assert.assertTrue(exe.canExecute(), "command must be executable: " + exe); + Assertions.assertTrue(exe.exists(), "command must exist: " + exe); + Assertions.assertTrue(exe.canExecute(), "command must be executable: " + exe); } if (info.arguments().isPresent()) { String[] args = info.arguments().get(); if (args.length > 0) { - Assert.assertEquals(args[0], String.valueOf(sleepTime)); + Assertions.assertEquals(String.valueOf(sleepTime), args[0]); } } p.destroy(); - Assert.assertTrue(p.waitFor(Utils.adjustTimeout(30), TimeUnit.SECONDS), + Assertions.assertTrue(p.waitFor(Utils.adjustTimeout(30), TimeUnit.SECONDS), "timeout waiting for process to terminate"); } } catch (IOException | InterruptedException ex) { @@ -332,7 +321,7 @@ public class InfoTest { * Cross check the cputime reported from java.management with that for the current process. */ @Test - public static void test4() { + public void test4() { Duration myCputime1 = ProcessUtil.MXBeanCpuTime(); if (Platform.isAix()) { @@ -367,26 +356,26 @@ public class InfoTest { Objects.toString(total2), myCputime2, myCputime2.minus(total2)); Duration epsilon = Duration.ofMillis(200L); // Epsilon is 200ms. - Assert.assertTrue(checkEpsilon(myCputime1, myCputime2, epsilon), + Assertions.assertTrue(checkEpsilon(myCputime1, myCputime2, epsilon), myCputime1.toNanos() + " should be within " + epsilon + " of " + myCputime2.toNanos()); - Assert.assertTrue(checkEpsilon(total1, total2, epsilon), + Assertions.assertTrue(checkEpsilon(total1, total2, epsilon), total1.toNanos() + " should be within " + epsilon + " of " + total2.toNanos()); - Assert.assertTrue(checkEpsilon(myCputime1, total1, epsilon), + Assertions.assertTrue(checkEpsilon(myCputime1, total1, epsilon), myCputime1.toNanos() + " should be within " + epsilon + " of " + total1.toNanos()); - Assert.assertTrue(checkEpsilon(total1, myCputime2, epsilon), + Assertions.assertTrue(checkEpsilon(total1, myCputime2, epsilon), total1.toNanos() + " should be within " + epsilon + " of " + myCputime2.toNanos()); - Assert.assertTrue(checkEpsilon(myCputime2, total2, epsilon), + Assertions.assertTrue(checkEpsilon(myCputime2, total2, epsilon), myCputime2.toNanos() + " should be within " + epsilon + " of " + total2.toNanos()); } } @Test - public static void test5() { + public void test5() { ProcessHandle self = ProcessHandle.current(); Random r = new Random(); for (int i = 0; i < 30; i++) { @@ -458,13 +447,12 @@ public class InfoTest { return; } String user = info.user().get(); - Assert.assertNotNull(user, "User name"); + Assertions.assertNotNull(user, "User name"); if (Platform.isWindows() && "BUILTIN\\Administrators".equals(whoami)) { int bsi = user.lastIndexOf("\\"); - Assert.assertEquals(bsi == -1 ? user : user.substring(bsi + 1), - System.getProperty("user.name"), "User name"); + Assertions.assertEquals(System.getProperty("user.name"), bsi == -1 ? user : user.substring(bsi + 1), "User name"); } else { - Assert.assertEquals(user, whoami, "User name"); + Assertions.assertEquals(whoami, user, "User name"); } } } diff --git a/test/jdk/java/lang/ProcessHandle/OnExitTest.java b/test/jdk/java/lang/ProcessHandle/OnExitTest.java index 79c696efdfc..45c2b51e398 100644 --- a/test/jdk/java/lang/ProcessHandle/OnExitTest.java +++ b/test/jdk/java/lang/ProcessHandle/OnExitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,37 +35,27 @@ import java.util.concurrent.TimeUnit; import jdk.test.lib.Platform; import jdk.test.lib.Utils; -import org.testng.annotations.Test; -import org.testng.Assert; -import org.testng.TestNG; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /* * @test + * @summary Functions of Process.onExit and ProcessHandle.onExit * @bug 8333742 * @requires vm.flagless * @library /test/lib * @modules jdk.management * @build jdk.test.lib.Utils - * @run testng OnExitTest - * @summary Functions of Process.onExit and ProcessHandle.onExit - * @author Roger Riggs + * @run junit OnExitTest */ public class OnExitTest extends ProcessUtil { - @SuppressWarnings("raw_types") - public static void main(String[] args) { - Class[] testclass = { OnExitTest.class}; - TestNG testng = new TestNG(); - testng.setTestClasses(testclass); - testng.run(); - } - /** * Basic test of exitValue and onExit. */ @Test - public static void test1() { + public void test1() { try { int[] exitValues = {0, 1, 10, 259}; for (int value : exitValues) { @@ -73,24 +63,24 @@ public class OnExitTest extends ProcessUtil { if (value == 259 && !Platform.isWindows()) continue; Process p = JavaChild.spawn("exit", Integer.toString(value)); CompletableFuture future = p.onExit(); - future.thenAccept( (ph) -> { + future.thenAccept((ph) -> { int actualExitValue = ph.exitValue(); printf(" javaChild done: %s, exitStatus: %d%n", ph, actualExitValue); - Assert.assertEquals(actualExitValue, value, "actualExitValue incorrect"); - Assert.assertEquals(ph, p, "Different Process passed to thenAccept"); + Assertions.assertEquals(value, actualExitValue, "actualExitValue incorrect"); + Assertions.assertEquals(p, ph, "Different Process passed to thenAccept"); }); Process h = future.get(); - Assert.assertEquals(h, p); - Assert.assertEquals(p.exitValue(), value); - Assert.assertFalse(p.isAlive(), "Process should not be alive"); - Assert.assertEquals(p.waitFor(), value); - Assert.assertTrue(p.waitFor(1, TimeUnit.MILLISECONDS), + Assertions.assertEquals(p, h); + Assertions.assertEquals(value, p.exitValue()); + Assertions.assertFalse(p.isAlive(), "Process should not be alive"); + Assertions.assertEquals(value, p.waitFor()); + Assertions.assertTrue(p.waitFor(1, TimeUnit.MILLISECONDS), "waitFor should return true"); } } catch (IOException | InterruptedException | ExecutionException ex) { - Assert.fail(ex.getMessage(), ex); + Assertions.fail(ex.getMessage(), ex); } finally { destroyProcessTree(ProcessHandle.current()); } @@ -101,7 +91,7 @@ public class OnExitTest extends ProcessUtil { * Spawn 1 child to spawn 3 children each with 2 children. */ @Test - public static void test2() { + public void test2() { // Please note (JDK-8284282): // @@ -176,7 +166,7 @@ public class OnExitTest extends ProcessUtil { // Check that each of the spawned processes is included in the children List remaining = new ArrayList<>(children); processes.forEach((p, parent) -> { - Assert.assertTrue(remaining.remove(p), "spawned process should have been in children"); + Assertions.assertTrue(remaining.remove(p), "spawned process should have been in children"); }); // Remove Win32 system spawned conhost.exe processes @@ -204,7 +194,7 @@ public class OnExitTest extends ProcessUtil { // Verify that all 9 exit handlers were called with the correct ProcessHandle processes.forEach((p, parent) -> { ProcessHandle value = completions.get(p).getNow(null); - Assert.assertEquals(p, value, "onExit.get value expected: " + p + Assertions.assertEquals(value, p, "onExit.get value expected: " + p + ", actual: " + value + ": " + p.info()); }); @@ -212,9 +202,9 @@ public class OnExitTest extends ProcessUtil { // Show the status of the original children children.forEach(p -> printProcess(p, "after onExit:")); - Assert.assertEquals(proc.isAlive(), false, "destroyed process is alive:: %s%n" + proc); + Assertions.assertFalse(proc.isAlive(), "destroyed process is alive:: %s%n" + proc); } catch (IOException | InterruptedException ex) { - Assert.fail(ex.getMessage()); + Assertions.fail(ex.getMessage(), ex); } finally { if (procHandle != null) { destroyProcessTree(procHandle); @@ -231,7 +221,7 @@ public class OnExitTest extends ProcessUtil { * Check that (B) does not complete until (A) has exited. */ @Test - public static void peerOnExitTest() { + public void peerOnExitTest() { String line = null; ArrayBlockingQueue alines = new ArrayBlockingQueue<>(100); ArrayBlockingQueue blines = new ArrayBlockingQueue<>(100); @@ -265,9 +255,9 @@ public class OnExitTest extends ProcessUtil { try { line = blines.poll(5L, TimeUnit.SECONDS); } catch (InterruptedException ie) { - Assert.fail("interrupted", ie); + Assertions.fail("interrupted", ie); } - Assert.assertNull(line, "waitpid didn't wait"); + Assertions.assertNull(line, "waitpid didn't wait"); A.toHandle().onExit().thenAccept(p -> { System.out.printf(" A.toHandle().onExit().A info: %s, now: %s%n", @@ -296,16 +286,16 @@ public class OnExitTest extends ProcessUtil { split = getSplitLine(blines); } while (!"waitpid".equals(split[1])); - Assert.assertEquals(split[2], "false", "Process A should not be alive"); + Assertions.assertEquals("false", split[2], "Process A should not be alive"); B.sendAction("exit", 0L); } catch (IOException ioe) { - Assert.fail("unable to start JavaChild B", ioe); + Assertions.fail("unable to start JavaChild B", ioe); } finally { B.destroyForcibly(); } } catch (IOException ioe2) { - Assert.fail("unable to start JavaChild A", ioe2); + Assertions.fail("unable to start JavaChild A", ioe2); } finally { A.destroyForcibly(); } @@ -328,7 +318,7 @@ public class OnExitTest extends ProcessUtil { } return split; } catch (InterruptedException ie) { - Assert.fail("interrupted", ie); + Assertions.fail("interrupted", ie); return null; } } diff --git a/test/jdk/java/lang/ProcessHandle/TreeTest.java b/test/jdk/java/lang/ProcessHandle/TreeTest.java index cec880f1fef..567cfea2895 100644 --- a/test/jdk/java/lang/ProcessHandle/TreeTest.java +++ b/test/jdk/java/lang/ProcessHandle/TreeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,12 +38,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.test.lib.Utils; -import org.testng.Assert; -import org.testng.TestNG; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /* * @test + * @summary Test counting and JavaChild.spawning and counting of Processes. * @requires vm.flagless * @library /test/lib * @modules java.base/jdk.internal.misc @@ -54,25 +54,15 @@ import org.testng.annotations.Test; * jdk.test.lib.JDKToolLauncher * jdk.test.lib.Platform * jdk.test.lib.process.* - * @run testng/othervm TreeTest - * @summary Test counting and JavaChild.spawning and counting of Processes. + * @run junit/othervm TreeTest * @author Roger Riggs */ public class TreeTest extends ProcessUtil { - // Main can be used to run the tests from the command line with only testng.jar. - @SuppressWarnings("raw_types") - public static void main(String[] args) { - Class[] testclass = {TreeTest.class}; - TestNG testng = new TestNG(); - testng.setTestClasses(testclass); - testng.run(); - } - /** * Test counting and spawning and counting of Processes. */ @Test - public static void test1() { + public void test1() { final int MAXCHILDREN = 2; List spawned = new ArrayList<>(); @@ -92,14 +82,14 @@ public class TreeTest extends ProcessUtil { spawned.stream() .map(Process::toHandle) .filter(p -> !initialChildren.contains(p)) - .forEach(p -> Assert.fail("Spawned process missing from children: " + p)); + .forEach(p -> Assertions.fail("Spawned process missing from children: " + p)); // Send exit command to each spawned Process spawned.forEach(p -> { try { p.sendAction("exit", ""); } catch (IOException ex) { - Assert.fail("IOException in sendAction", ex); + Assertions.fail("IOException in sendAction", ex); } }); @@ -107,7 +97,7 @@ public class TreeTest extends ProcessUtil { spawned.forEach(p -> { do { try { - Assert.assertEquals(p.waitFor(), 0, "exit status incorrect"); + Assertions.assertEquals(0, p.waitFor(), "exit status incorrect"); break; } catch (InterruptedException ex) { continue; // Retry @@ -118,7 +108,7 @@ public class TreeTest extends ProcessUtil { // Verify that ProcessHandle.isAlive sees each of them as not alive for (Process p : spawned) { ProcessHandle ph = p.toHandle(); - Assert.assertFalse(ph.isAlive(), + Assertions.assertFalse(ph.isAlive(), "ProcessHandle.isAlive for exited process: " + ph); } @@ -126,13 +116,13 @@ public class TreeTest extends ProcessUtil { final List afterChildren = getChildren(self); spawned.stream() .map(Process::toHandle) - .filter(p -> afterChildren.contains(p)) - .forEach(p -> Assert.fail("Spawned process missing from children: " + p)); + .filter(afterChildren::contains) + .forEach(p -> Assertions.fail("Spawned process missing from children: " + p)); } catch (IOException ioe) { - Assert.fail("unable to spawn process", ioe); + Assertions.fail("unable to spawn process", ioe); } finally { - // Cleanup any left over processes + // Cleanup any leftover processes spawned.stream() .map(Process::toHandle) .filter(ProcessHandle::isAlive) @@ -147,7 +137,7 @@ public class TreeTest extends ProcessUtil { * Test counting and spawning and counting of Processes. */ @Test - public static void test2() { + public void test2() { try { ConcurrentHashMap processes = new ConcurrentHashMap<>(); @@ -162,12 +152,12 @@ public class TreeTest extends ProcessUtil { ProcessHandle p1Handle = p1.toHandle(); printf(" p1 pid: %d%n", p1.pid()); - // Gather the PIDs from the output of the spawing process + // Gather the PIDs from the output of the spawning process p1.forEachOutputLine((s) -> { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("spawn")) { - Long child = Long.valueOf(split[2]); - Long parent = Long.valueOf(split[0].split(":")[0]); + long child = Long.parseLong(split[2]); + long parent = Long.parseLong(split[0].split(":")[0]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); } }); @@ -179,11 +169,11 @@ public class TreeTest extends ProcessUtil { List subprocesses = waitForAllChildren(p1Handle, spawnNew); Optional p1Start = p1Handle.info().startInstant(); for (ProcessHandle ph : subprocesses) { - Assert.assertTrue(ph.isAlive(), "Child should be alive: " + ph); + Assertions.assertTrue(ph.isAlive(), "Child should be alive: " + ph); // Verify each child was started after the parent ph.info().startInstant() .ifPresent(childStart -> p1Start.ifPresent(parentStart -> { - Assert.assertFalse(childStart.isBefore(parentStart), + Assertions.assertFalse(childStart.isBefore(parentStart), String.format("Child process started before parent: child: %s, parent: %s", childStart, parentStart)); })); @@ -217,8 +207,8 @@ public class TreeTest extends ProcessUtil { // Verify that all spawned children show up in the descendants List processes.forEach((p, parent) -> { - Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p); - Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p); + Assertions.assertTrue(p.isAlive(), "Child should be alive: " + p); + Assertions.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p); }); // Closing JavaChild's InputStream will cause all children to exit @@ -228,13 +218,13 @@ public class TreeTest extends ProcessUtil { try { p.onExit().get(); // wait for the child to exit } catch (ExecutionException e) { - Assert.fail("waiting for process to exit", e); + Assertions.fail("waiting for process to exit", e); } } p1.waitFor(); // wait for spawned process to exit // Verify spawned processes are no longer alive - processes.forEach((ph, parent) -> Assert.assertFalse(ph.isAlive(), + processes.forEach((ph, parent) -> Assertions.assertFalse(ph.isAlive(), "process should not be alive: " + ph)); } catch (IOException | InterruptedException t) { t.printStackTrace(); @@ -250,7 +240,7 @@ public class TreeTest extends ProcessUtil { * After they exit they should no longer be listed by descendants. */ @Test - public static void test3() { + public void test3() { ConcurrentHashMap processes = new ConcurrentHashMap<>(); try { @@ -269,15 +259,15 @@ public class TreeTest extends ProcessUtil { p1.forEachOutputLine((s) -> { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("spawn")) { - Long child = Long.valueOf(split[2]); - Long parent = Long.valueOf(split[0].split(":")[0]); + long child = Long.parseLong(split[2]); + long parent = Long.parseLong(split[0].split(":")[0]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); spawnCount.countDown(); } }); // Wait for all the subprocesses to be listed as started - Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), + Assertions.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), "Timeout waiting for processes to start"); // Debugging; list descendants that are not expected in processes @@ -290,17 +280,17 @@ public class TreeTest extends ProcessUtil { .filter(ph -> !processes.containsKey(ph)) .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); ProcessUtil.logTaskList(); - Assert.assertEquals(0, count, "Extra processes in descendants"); + Assertions.assertEquals(0, count, "Extra processes in descendants"); } // Verify that all spawned children are alive, show up in the descendants list // then destroy them processes.forEach((p, parent) -> { - Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p); - Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p); + Assertions.assertTrue(p.isAlive(), "Child should be alive: " + p); + Assertions.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p); p.destroyForcibly(); }); - Assert.assertEquals(processes.size(), newChildren, "Wrong number of children"); + Assertions.assertEquals(newChildren, processes.size(), "Wrong number of children"); // Wait for each of the processes to exit processes.forEach((p, parent) -> { @@ -317,21 +307,21 @@ public class TreeTest extends ProcessUtil { } printf("Timeout waiting for exit of pid %s, parent: %s, info: %s%n", p, parent, p.info()); - Assert.fail("Process still alive: " + p); + Assertions.fail("Process still alive: " + p); }); p1.destroyForcibly(); p1.waitFor(); // Verify that none of the spawned children are still listed by descendants List remaining = getDescendants(self); - Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited"); + Assertions.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited"); remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList()); - Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining); + Assertions.assertEquals(0, remaining.size(), "Subprocess(es) should have exited: " + remaining); } catch (IOException ioe) { - Assert.fail("Spawn of subprocess failed", ioe); + Assertions.fail("Spawn of subprocess failed", ioe); } catch (InterruptedException inte) { - Assert.fail("InterruptedException", inte); + Assertions.fail("InterruptedException", inte); } finally { processes.forEach((p, parent) -> { if (p.isAlive()) { @@ -346,7 +336,7 @@ public class TreeTest extends ProcessUtil { * Test (Not really a test) that dumps the list of all Processes. */ @Test - public static void test4() { + public void test4() { printf(" Parent Child Info%n"); Stream s = ProcessHandle.allProcesses(); ProcessHandle[] processes = s.toArray(ProcessHandle[]::new); @@ -384,7 +374,7 @@ public class TreeTest extends ProcessUtil { } printf("%s %7s, %7s, %s%n", indent, p_parent, p, info); } - Assert.assertFalse(fail, "Parents missing from all Processes"); + Assertions.assertFalse(fail, "Parents missing from all Processes"); } @@ -392,7 +382,7 @@ public class TreeTest extends ProcessUtil { * A test for scale; launch a large number (14) of subprocesses. */ @Test - public static void test5() { + public void test5() { ConcurrentHashMap processes = new ConcurrentHashMap<>(); int factor = 2; @@ -421,15 +411,15 @@ public class TreeTest extends ProcessUtil { p1.forEachOutputLine((s) -> { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("spawn")) { - Long child = Long.valueOf(split[2]); - Long parent = Long.valueOf(split[0].split(":")[0]); + long child = Long.parseLong(split[2]); + long parent = Long.parseLong(split[0].split(":")[0]); processes.put(ProcessHandle.of(child).get(), ProcessHandle.of(parent).get()); spawnCount.countDown(); } }); // Wait for all the subprocesses to be listed as started - Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), + Assertions.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS), "Timeout waiting for processes to start"); // Debugging; list descendants that are not expected in processes @@ -442,30 +432,29 @@ public class TreeTest extends ProcessUtil { .filter(ph -> !processes.containsKey(ph)) .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: ")); ProcessUtil.logTaskList(); - Assert.assertEquals(0, count, "Extra processes in descendants"); + Assertions.assertEquals(0, count, "Extra processes in descendants"); } List subprocesses = getChildren(p1Handle); printf(" children: %s%n", - subprocesses.stream().map(p -> p.pid()) + subprocesses.stream().map(ProcessHandle::pid) .collect(Collectors.toList())); - Assert.assertEquals(getChildren(p1Handle).size(), - factor, "expected direct children"); + Assertions.assertEquals(factor, getChildren(p1Handle).size(), "expected direct children"); count = getDescendants(p1Handle).size(); long totalChildren = factor * factor * factor + factor * factor + factor; - Assert.assertTrue(count >= totalChildren, + Assertions.assertTrue(count >= totalChildren, "expected at least " + totalChildren + ", actual: " + count); List descSubprocesses = getDescendants(p1Handle); printf(" descendants: %s%n", - descSubprocesses.stream().map(p -> p.pid()) + descSubprocesses.stream().map(ProcessHandle::pid) .collect(Collectors.toList())); p1.getOutputStream().close(); // Close stdin for the controlling p1 p1.waitFor(); } catch (InterruptedException | IOException ex) { - Assert.fail("Unexpected Exception", ex); + Assertions.fail("Unexpected Exception", ex); } finally { printf("Duration: %s%n", Duration.between(start, Instant.now())); if (p1 != null) { From 4d42ce23f03ecf256ff4af66446a9b263e37a186 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 10 Mar 2026 13:22:04 +0000 Subject: [PATCH 143/170] 8379499: [AIX] headless-only build of libjawt.so fails Reviewed-by: mdoerr --- make/modules/java.desktop/lib/AwtLibraries.gmk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/make/modules/java.desktop/lib/AwtLibraries.gmk b/make/modules/java.desktop/lib/AwtLibraries.gmk index 8b6b50b9e62..1aa2578d2e2 100644 --- a/make/modules/java.desktop/lib/AwtLibraries.gmk +++ b/make/modules/java.desktop/lib/AwtLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -423,6 +423,9 @@ endif ifeq ($(call isTargetOs, linux)+$(ENABLE_HEADLESS_ONLY), true+true) LIBJAWT_CFLAGS += -DHEADLESS endif +ifeq ($(call isTargetOs, aix)+$(ENABLE_HEADLESS_ONLY), true+true) + LIBJAWT_CFLAGS += -DHEADLESS +endif ifeq ($(call isTargetOs, windows)+$(call isTargetCpu, x86), true+true) LIBJAWT_LIBS_windows := kernel32.lib From 34fa46758dc12f82a9d0249ec62f1fad859af02c Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 10 Mar 2026 15:02:17 +0000 Subject: [PATCH 144/170] 8379364: Shenandoah: Remove duplicate semicolons in GenShen code Reviewed-by: wkemper --- .../heuristics/shenandoahAdaptiveHeuristics.cpp | 2 +- .../heuristics/shenandoahGenerationalHeuristics.cpp | 2 +- src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp | 8 ++++---- .../gc/shenandoah/shenandoahGenerationalControlThread.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index a1aeb918553..6b327d7e4af 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -273,7 +273,7 @@ void ShenandoahAdaptiveHeuristics::add_gc_time(double timestamp, double gc_time) } double ShenandoahAdaptiveHeuristics::predict_gc_time(double timestamp_at_start) { - return _gc_time_m * timestamp_at_start + _gc_time_b + _gc_time_sd * _margin_of_error_sd;; + return _gc_time_m * timestamp_at_start + _gc_time_b + _gc_time_sd * _margin_of_error_sd; } void ShenandoahAdaptiveHeuristics::add_rate_to_acceleration_history(double timestamp, double rate) { diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index 4b665501d71..bcf4197f86d 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -509,7 +509,7 @@ void ShenandoahGenerationalHeuristics::adjust_evacuation_budgets(ShenandoahHeap* size_t young_evacuated = collection_set->get_live_bytes_in_untenurable_regions(); size_t young_evacuated_reserve_used = (size_t) (ShenandoahEvacWaste * double(young_evacuated)); - size_t total_young_available = young_generation->available_with_reserve() - _add_regions_to_old * region_size_bytes;; + size_t total_young_available = young_generation->available_with_reserve() - _add_regions_to_old * region_size_bytes; assert(young_evacuated_reserve_used <= total_young_available, "Cannot evacuate (%zu) more than is available in young (%zu)", young_evacuated_reserve_used, total_young_available); young_generation->set_evacuation_reserve(young_evacuated_reserve_used); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index d765f33fee0..a579d6d3694 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -348,7 +348,7 @@ void ShenandoahRegionPartitions::make_all_regions_unavailable() { _leftmosts[partition_id] = _max; _rightmosts[partition_id] = -1; _leftmosts_empty[partition_id] = _max; - _rightmosts_empty[partition_id] = -1;; + _rightmosts_empty[partition_id] = -1; _capacity[partition_id] = 0; _region_counts[partition_id] = 0; _empty_region_counts[partition_id] = 0; @@ -445,7 +445,7 @@ void ShenandoahRegionPartitions::increase_humongous_waste(ShenandoahFreeSetParti size_t ShenandoahRegionPartitions::get_humongous_waste(ShenandoahFreeSetPartitionId which_partition) { assert (which_partition < NumPartitions, "Partition must be valid"); - return _humongous_waste[int(which_partition)];; + return _humongous_waste[int(which_partition)]; } void ShenandoahRegionPartitions::set_capacity_of(ShenandoahFreeSetPartitionId which_partition, size_t value) { @@ -510,7 +510,7 @@ void ShenandoahRegionPartitions::decrease_available(ShenandoahFreeSetPartitionId size_t ShenandoahRegionPartitions::get_available(ShenandoahFreeSetPartitionId which_partition) { assert (which_partition < NumPartitions, "Partition must be valid"); - return _available[int(which_partition)];; + return _available[int(which_partition)]; } void ShenandoahRegionPartitions::increase_region_counts(ShenandoahFreeSetPartitionId which_partition, size_t regions) { @@ -2799,7 +2799,7 @@ size_t ShenandoahFreeSet::reserve_regions(size_t to_reserve, size_t to_reserve_o size_t empty_regions_to_collector = 0; size_t empty_regions_to_old_collector = 0; - size_t old_collector_available = _partitions.available_in(ShenandoahFreeSetPartitionId::OldCollector);; + size_t old_collector_available = _partitions.available_in(ShenandoahFreeSetPartitionId::OldCollector); size_t collector_available = _partitions.available_in(ShenandoahFreeSetPartitionId::Collector); for (size_t i = _heap->num_regions(); i > 0; i--) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index cc7547b8ac1..5f201a404d8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -186,7 +186,7 @@ ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread: global_heuristics->record_requested_gc(); if (ShenandoahCollectorPolicy::should_run_full_gc(request.cause)) { - return stw_full;; + return stw_full; } else { // Unload and clean up everything. Note that this is an _explicit_ request and so does not use // the same `should_unload_classes` call as the regulator's concurrent gc request. From 59301499871bcaee3d79fa1d876630de52c89db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Tue, 10 Mar 2026 15:02:36 +0000 Subject: [PATCH 145/170] 8379487: Dangling static ref to fallback error in libinstrument's JavaExceptions.c Reviewed-by: cjplummer, kbarrett --- .../share/native/libinstrument/JavaExceptions.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/java.instrument/share/native/libinstrument/JavaExceptions.c b/src/java.instrument/share/native/libinstrument/JavaExceptions.c index 0a787ce4150..45c31e329d0 100644 --- a/src/java.instrument/share/native/libinstrument/JavaExceptions.c +++ b/src/java.instrument/share/native/libinstrument/JavaExceptions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,9 +68,20 @@ forceFallback(jthrowable potentialException) { jboolean initializeFallbackError(JNIEnv* jnienv) { jplis_assert(isSafeForJNICalls(jnienv)); - sFallbackInternalError = createInternalError(jnienv, NULL); + jthrowable localRef = createInternalError(jnienv, NULL); + if (localRef == NULL) { + return JNI_FALSE; + } + + jthrowable globalRef = (*jnienv)->NewGlobalRef(jnienv, localRef); + if (globalRef == NULL) { + return JNI_FALSE; + } + + sFallbackInternalError = globalRef; jplis_assert(isSafeForJNICalls(jnienv)); - return (sFallbackInternalError != NULL); + + return JNI_TRUE; } From e24a8f06e30a0889b1fb5689ac3d4180f90d25d4 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 10 Mar 2026 15:05:26 +0000 Subject: [PATCH 146/170] 8378201: [OGL] glXMakeContextCurrent() drops the buffers of the unbound drawable 8369561: sun/java2d/OpenGL/DrawBitmaskImage.java#id0: Incorrect color for first pixel (actual=ff000000) Reviewed-by: prr, aivanov --- .../common/java2d/opengl/GLXSurfaceData.c | 100 ++++++++++++- test/jdk/ProblemList.txt | 1 + .../sun/java2d/OpenGL/FlipCoexistTest.java | 134 ++++++++++++++++++ .../java2d/OpenGL/MultiWindowFillTest.java | 122 ++++++++++++++++ 4 files changed, 352 insertions(+), 5 deletions(-) create mode 100644 test/jdk/sun/java2d/OpenGL/FlipCoexistTest.java create mode 100644 test/jdk/sun/java2d/OpenGL/MultiWindowFillTest.java diff --git a/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c b/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c index 8f264278d9f..0497dbf69fa 100644 --- a/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c +++ b/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,8 @@ #ifndef HEADLESS +#include + extern LockFunc OGLSD_Lock; extern GetRasInfoFunc OGLSD_GetRasInfo; extern UnlockFunc OGLSD_Unlock; @@ -50,6 +52,74 @@ extern void jboolean surfaceCreationFailed = JNI_FALSE; +/** + * Per-Window GLXWindow entry with reference counting. + * Stored in an XContext keyed by the X Window XID. + */ +typedef struct { + GLXWindow glxWindow; + int refCount; +} GLXWindowRef; + +static XContext glxWindowContext; + +/** + * Gets or creates a shared GLXWindow for the given X Window. + * All callers are synchronized by the AWT lock. + */ +static GLXWindow acquireGLXWindow(Window window, GLXFBConfig fbconfig) +{ + if (glxWindowContext == 0) { + glxWindowContext = XUniqueContext(); + } + + XPointer data; + if (XFindContext(awt_display, window, glxWindowContext, &data) == 0) { + GLXWindowRef *ref = (GLXWindowRef *)data; + ref->refCount++; + return ref->glxWindow; + } + + GLXWindow glxWin = j2d_glXCreateWindow(awt_display, fbconfig, window, NULL); + if (glxWin == 0) { + return 0; + } + + GLXWindowRef *ref = malloc(sizeof(*ref)); + if (ref == NULL) { + j2d_glXDestroyWindow(awt_display, glxWin); + return 0; + } + ref->glxWindow = glxWin; + ref->refCount = 1; + if (XSaveContext(awt_display, window, glxWindowContext, (XPointer)ref) != 0) + { + j2d_glXDestroyWindow(awt_display, glxWin); + free(ref); + return 0; + } + return glxWin; +} + +/** + * Decrements the reference count for the GLXWindow associated with the given + * X Window. Destroys it when the count reaches zero. + * All callers are synchronized by the AWT lock. + */ +static void releaseGLXWindow(Window window) +{ + XPointer data; + if (XFindContext(awt_display, window, glxWindowContext, &data) != 0) { + return; + } + GLXWindowRef *ref = (GLXWindowRef *)data; + if (--ref->refCount <= 0) { + j2d_glXDestroyWindow(awt_display, ref->glxWindow); + XDeleteContext(awt_display, window, glxWindowContext); + free(ref); + } +} + #endif /* !HEADLESS */ JNIEXPORT void JNICALL @@ -74,7 +144,7 @@ Java_sun_java2d_opengl_GLXSurfaceData_initOps(JNIEnv *env, jobject glxsd, // later the graphicsConfig will be used for deallocation of oglsdo oglsdo->graphicsConfig = gc; - GLXSDOps *glxsdo = (GLXSDOps *)malloc(sizeof(GLXSDOps)); + GLXSDOps *glxsdo = (GLXSDOps *)calloc(1, sizeof(GLXSDOps)); if (glxsdo == NULL) { JNU_ThrowOutOfMemoryError(env, "creating native GLX ops"); @@ -125,8 +195,13 @@ Java_sun_java2d_opengl_GLXSurfaceData_initOps(JNIEnv *env, jobject glxsd, void OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo) { + GLXSDOps *glxsdo = (GLXSDOps *)oglsdo->privOps; J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface"); - // X Window is free'd later by AWT code... + if (glxsdo != NULL && glxsdo->drawable != 0) { + releaseGLXWindow(glxsdo->window); + glxsdo->drawable = 0; + oglsdo->drawableType = OGLSD_UNDEFINED; + } } /** @@ -296,6 +371,13 @@ OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo) return JNI_FALSE; } + glxsdo->drawable = acquireGLXWindow(window, + glxsdo->configData->glxInfo->fbconfig); + if (glxsdo->drawable == 0) { + J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitOGLWindow: GLXWindow is 0"); + return JNI_FALSE; + } + XGetWindowAttributes(awt_display, window, &attr); oglsdo->width = attr.width; oglsdo->height = attr.height; @@ -304,7 +386,6 @@ OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo) oglsdo->isOpaque = JNI_TRUE; oglsdo->xOffset = 0; oglsdo->yOffset = 0; - glxsdo->drawable = window; glxsdo->xdrawable = window; J2dTraceLn(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", @@ -333,7 +414,16 @@ OGLSD_SwapBuffers(JNIEnv *env, jlong window) return; } - j2d_glXSwapBuffers(awt_display, (Window)window); + XPointer data; + if (XFindContext(awt_display, (Window)window, glxWindowContext, &data) != 0) + { + J2dRlsTraceLn(J2D_TRACE_ERROR, + "OGLSD_SwapBuffers: GLXWindow not found"); + return; + } + + GLXWindowRef *ref = (GLXWindowRef *)data; + j2d_glXSwapBuffers(awt_display, ref->glxWindow); } // needed by Mac OS X port, no-op on other platforms diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 070f9b0ce03..62faf5b9b33 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -222,6 +222,7 @@ sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all sun/java2d/DirectX/OverriddenInsetsTest/OverriddenInsetsTest.java 8196102 generic-all sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all +sun/java2d/OpenGL/MultiWindowFillTest.java 8378506 macosx-all sun/java2d/OpenGL/OpaqueDest.java#id1 8367574 macosx-all sun/java2d/OpenGL/ScaleParamsOOB.java#id0 8377908 linux-all sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all diff --git a/test/jdk/sun/java2d/OpenGL/FlipCoexistTest.java b/test/jdk/sun/java2d/OpenGL/FlipCoexistTest.java new file mode 100644 index 00000000000..beb5da887b4 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/FlipCoexistTest.java @@ -0,0 +1,134 @@ +/* + * 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. + */ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferStrategy; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8378201 + * @key headful + * @summary Verifies that WINDOW and FLIP_BACKBUFFER surfaces sharing the same X + * Window render and flip correctly + * @run main/othervm FlipCoexistTest + * @run main/othervm -Dsun.java2d.opengl=True FlipCoexistTest + */ +public final class FlipCoexistTest { + + private static final int SIZE = 200; + private static final int TOLERANCE = 10; + + public static void main(String[] args) throws Exception { + Frame f = new Frame("FlipCoexistTest"); + try { + f.setUndecorated(true); + f.setSize(SIZE, SIZE); + f.setLocation(100, 100); + f.setVisible(true); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + int w = f.getWidth(); + int h = f.getHeight(); + + // Fill window RED via direct render (WINDOW surface) + Graphics g = f.getGraphics(); + g.setColor(Color.RED); + g.fillRect(0, 0, w, h); + g.dispose(); + robot.waitForIdle(); + robot.delay(500); + + // Request flip if available, blit is also useful to cover + f.createBufferStrategy(2); + BufferStrategy bs = f.getBufferStrategy(); + + // Render BLUE to back buffer, do not flip yet + Graphics bg = bs.getDrawGraphics(); + bg.setColor(Color.BLUE); + bg.fillRect(0, 0, w, h); + bg.dispose(); + + // Paint small GREEN rect via direct render + g = f.getGraphics(); + g.setColor(Color.GREEN); + g.fillRect(0, 0, 10, 10); + g.dispose(); + robot.waitForIdle(); + robot.delay(500); + + // GREEN rect must be visible + check(robot, f, 5, 5, Color.GREEN, "small rect"); + + // RED must survive the context round-trip + check(robot, f, w / 2, h / 2, Color.RED, "survived"); + + // Show back buffer, BLUE must appear + bs.show(); + + robot.waitForIdle(); + robot.delay(500); + check(robot, f, w / 2, h / 2, Color.BLUE, "flip"); + } finally { + f.dispose(); + } + } + + private static void check(Robot robot, Frame frame, int x, int y, Color exp, + String desc) + { + Point loc = frame.getLocationOnScreen(); + Color c = robot.getPixelColor(loc.x + x, loc.y + y); + if (!isAlmostEqual(c, exp)) { + saveImage(robot, frame, desc); + throw new RuntimeException("%s: %s != %s".formatted(desc, exp, c)); + } + } + + private static void saveImage(Robot r, Frame f, String name) { + try { + Rectangle rect = f.getBounds(); + BufferedImage img = r.createScreenCapture(rect); + ImageIO.write(img, "png", new File(name + ".png")); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static boolean isAlmostEqual(Color c1, Color c2) { + return Math.abs(c1.getRed() - c2.getRed()) <= TOLERANCE + && Math.abs(c1.getGreen() - c2.getGreen()) <= TOLERANCE + && Math.abs(c1.getBlue() - c2.getBlue()) <= TOLERANCE; + } +} diff --git a/test/jdk/sun/java2d/OpenGL/MultiWindowFillTest.java b/test/jdk/sun/java2d/OpenGL/MultiWindowFillTest.java new file mode 100644 index 00000000000..59c58d944d7 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/MultiWindowFillTest.java @@ -0,0 +1,122 @@ +/* + * 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. + */ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.io.File; + +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8378201 + * @key headful + * @summary Verifies that window content survives a GL context switch to another + * window and back + * @run main/othervm MultiWindowFillTest + * @run main/othervm -Dsun.java2d.opengl=True MultiWindowFillTest + */ +public final class MultiWindowFillTest { + + private static final int SIZE = 100; + private static final int TOLERANCE = 10; + + public static void main(String[] args) throws Exception { + Frame f1 = new Frame("f1"); + Frame f2 = new Frame("f2"); + try { + f1.setUndecorated(true); + f1.setSize(SIZE, SIZE); + f1.setLocation(100, 100); + f2.setUndecorated(true); + f2.setSize(SIZE, SIZE); + f2.setLocation(300, 100); + + f1.setVisible(true); + f2.setVisible(true); + + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + + int w = f1.getWidth(); + int h = f1.getHeight(); + + // Fill both, initializes surfaces + fill(f1, Color.RED, w, h); + fill(f2, Color.BLUE, w, h); + + // Touch both again + fill(f1, Color.RED, 2, 2); + fill(f2, Color.BLUE, 2, 2); + + robot.waitForIdle(); + robot.delay(1000); + + check(robot, f1, w, h, Color.RED, "f1 red"); + check(robot, f2, w, h, Color.BLUE, "f2 blue"); + } finally { + f1.dispose(); + f2.dispose(); + } + } + + private static void fill(Frame frame, Color c, int w, int h) { + Graphics g = frame.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, w, h); + g.dispose(); + } + + private static void check(Robot robot, Frame frame, int w, int h, + Color exp, String desc) + { + Point loc = frame.getLocationOnScreen(); + Color c = robot.getPixelColor(loc.x + w / 2, loc.y + h / 2); + if (!isAlmostEqual(c, exp)) { + saveImage(robot, frame, desc); + throw new RuntimeException("%s: %s != %s".formatted(desc, exp, c)); + } + } + + private static void saveImage(Robot r, Frame f, String name) { + try { + Rectangle rect = f.getBounds(); + BufferedImage img = r.createScreenCapture(rect); + ImageIO.write(img, "png", new File(name + ".png")); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static boolean isAlmostEqual(Color c1, Color c2) { + return Math.abs(c1.getRed() - c2.getRed()) <= TOLERANCE + && Math.abs(c1.getGreen() - c2.getGreen()) <= TOLERANCE + && Math.abs(c1.getBlue() - c2.getBlue()) <= TOLERANCE; + } +} From 5aa115b569bb6617a67dbb5297a9ec0fd36a3390 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 10 Mar 2026 15:38:37 +0000 Subject: [PATCH 147/170] 8379622: Problemlist java/nio/channels/SocketChannel/OpenLeak.java and CloseDuringConnect.java on macos 26 Reviewed-by: alanb --- test/jdk/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 62faf5b9b33..de1a0a49d1e 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -570,6 +570,8 @@ java/nio/channels/DatagramChannel/Unref.java 8233437 generic- java/nio/channels/DatagramChannel/BasicMulticastTests.java 8144003 macosx-all java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java 8144003 macosx-all java/nio/channels/DatagramChannel/Promiscuous.java 8144003 macosx-all +java/nio/channels/SocketChannel/CloseDuringConnect.java 8375658 macosx-26.0,macosx-26.1,macosx-26.2,macosx-26.3 +java/nio/channels/SocketChannel/OpenLeak.java 8375658 macosx-26.0,macosx-26.1,macosx-26.2,macosx-26.3 ############################################################################ From 680503cf8201f5f2d1fd99df32716e66e92a0974 Mon Sep 17 00:00:00 2001 From: Volodymyr Paprotski Date: Tue, 10 Mar 2026 15:59:34 +0000 Subject: [PATCH 148/170] 8378470: Add future Intel family number Reviewed-by: dholmes, sviswanathan --- src/hotspot/cpu/x86/vm_version_x86.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index e0a895737b7..9f0446df7c6 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -828,7 +828,7 @@ public: static uint32_t cpu_stepping() { return _cpuid_info.cpu_stepping(); } static int cpu_family() { return _cpu;} static bool is_P6() { return cpu_family() >= 6; } - static bool is_intel_server_family() { return cpu_family() == 6 || cpu_family() == 19; } + static bool is_intel_server_family() { return cpu_family() == 6 || cpu_family() == 18 || cpu_family() == 19; } static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA' static bool is_hygon() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x6F677948; } // 'ogyH' static bool is_amd_family() { return is_amd() || is_hygon(); } From d3158e71c6a0b5a78a04fc9a7e2d33174cb7fe49 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Tue, 10 Mar 2026 16:05:04 +0000 Subject: [PATCH 149/170] 8379628: Refactor langtools/shellsupport/doc tests to use JUnit Reviewed-by: hannesw --- .../doc/FullJavadocHelperTest.java | 8 ++--- .../doc/JavadocFormatterTest.java | 9 +++--- .../shellsupport/doc/JavadocHelperTest.java | 31 ++++++++++++++----- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/test/langtools/jdk/internal/shellsupport/doc/FullJavadocHelperTest.java b/test/langtools/jdk/internal/shellsupport/doc/FullJavadocHelperTest.java index fcfd40b3292..5219b8e9080 100644 --- a/test/langtools/jdk/internal/shellsupport/doc/FullJavadocHelperTest.java +++ b/test/langtools/jdk/internal/shellsupport/doc/FullJavadocHelperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,19 +30,19 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.jshell/jdk.internal.shellsupport.doc * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask - * @run testng/timeout=900/othervm -Xmx1024m FullJavadocHelperTest + * @run junit/timeout=900/othervm -Xmx1024m FullJavadocHelperTest */ import java.io.IOException; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; -@Test public class FullJavadocHelperTest { /* * Long-running test to retrieve doc comments for enclosed elements of all JDK classes. */ + @Test public void testAllDocs() throws IOException { new JavadocHelperTest().retrieveDocComments(Boolean.TRUE::booleanValue); } diff --git a/test/langtools/jdk/internal/shellsupport/doc/JavadocFormatterTest.java b/test/langtools/jdk/internal/shellsupport/doc/JavadocFormatterTest.java index 153c010c33d..2ee326e26f9 100644 --- a/test/langtools/jdk/internal/shellsupport/doc/JavadocFormatterTest.java +++ b/test/langtools/jdk/internal/shellsupport/doc/JavadocFormatterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,21 +27,21 @@ * @summary Test JavadocFormatter * @library /tools/lib * @modules jdk.jshell/jdk.internal.shellsupport.doc - * @run testng JavadocFormatterTest + * @run junit JavadocFormatterTest */ import java.util.Objects; import jdk.internal.shellsupport.doc.JavadocFormatter; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; -@Test public class JavadocFormatterTest { private static final String CODE_RESET = "\033[0m"; private static final String CODE_HIGHLIGHT = "\033[1m"; private static final String CODE_UNDERLINE = "\033[4m"; + @Test public void testReflow() { String actual; String expected; @@ -401,6 +401,7 @@ public class JavadocFormatterTest { } } + @Test public void testSpaceAtEndOfLine() { String header = "Class Class.forName(Module module, String name)"; String javadoc = """ diff --git a/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java b/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java index e82553a4cfe..4f739d38d3d 100644 --- a/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java +++ b/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.jshell/jdk.internal.shellsupport.doc * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask - * @run testng JavadocHelperTest + * @run junit JavadocHelperTest * @key randomness */ @@ -69,13 +69,13 @@ import javax.tools.ToolProvider; import com.sun.source.util.JavacTask; import jdk.internal.shellsupport.doc.JavadocHelper; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; -@Test public class JavadocHelperTest { + @Test public void testJavadoc() throws Exception { doTestJavadoc("", t -> t.getElements().getTypeElement("test.Super"), @@ -93,6 +93,7 @@ public class JavadocHelperTest { " @return value\n"); } + @Test public void testInheritNoJavadoc() throws Exception { doTestJavadoc("", getSubTest, @@ -107,6 +108,7 @@ public class JavadocHelperTest { " @return value\n"); } + @Test public void testInheritFull() throws Exception { doTestJavadoc(" /**\n" + " * Prefix {@inheritDoc} suffix.\n" + @@ -131,6 +133,7 @@ public class JavadocHelperTest { " @return prefix value suffix\n"); } + @Test public void testInheritMissingParam() throws Exception { doTestJavadoc(" /**\n" + " * Prefix {@inheritDoc} suffix.\n" + @@ -154,6 +157,7 @@ public class JavadocHelperTest { " @return prefix value suffix\n"); } + @Test public void testInheritMissingFirstParam() throws Exception { doTestJavadoc(" /**\n" + " * Prefix {@inheritDoc} suffix.\n" + @@ -177,6 +181,7 @@ public class JavadocHelperTest { " @return prefix value suffix\n"); } + @Test public void testInheritMissingThrows() throws Exception { doTestJavadoc(" /**\n" + " * Prefix {@inheritDoc} suffix.\n" + @@ -200,6 +205,7 @@ public class JavadocHelperTest { " @return prefix value suffix\n"); } + @Test public void testInheritMissingReturn() throws Exception { doTestJavadoc(" /**\n" + " * Prefix {@inheritDoc} suffix.\n" + @@ -223,6 +229,7 @@ public class JavadocHelperTest { "@return value\n"); } + @Test public void testInheritAllButOne() throws Exception { doTestJavadoc(" /**\n" + " * @throws IllegalArgumentException {@inheritDoc}\n" + @@ -238,6 +245,7 @@ public class JavadocHelperTest { "@return value\n"); } + @Test public void testInheritEmpty() throws Exception { doTestJavadoc(" /**\n" + " */\n", @@ -260,6 +268,7 @@ public class JavadocHelperTest { "@return \n"); } + @Test public void testEmptyValue() throws Exception { doTestJavadoc(" /**\n" + " */\n", @@ -282,6 +291,7 @@ public class JavadocHelperTest { "@return \n"); } + @Test public void testShortComment() throws Exception { doTestJavadoc(" /**Test.*/\n", getSubTest, @@ -295,6 +305,7 @@ public class JavadocHelperTest { "@return value\n"); } + @Test public void testMarkdown() throws Exception { doTestJavadoc(""" /// Prefix {@inheritDoc} suffix. @@ -328,6 +339,7 @@ public class JavadocHelperTest { @return prefix value suffix"""); } + @Test public void testMarkdown2() throws Exception { doTestJavadoc(""" /// {@inheritDoc} @@ -352,6 +364,7 @@ public class JavadocHelperTest { @since snc"""); } + @Test public void testMarkdown3() throws Exception { doTestJavadoc(""" /// {@inheritDoc} @@ -373,6 +386,7 @@ public class JavadocHelperTest { """); } + @Test public void testMarkdown4() throws Exception { doTestJavadoc(""" /// {@inheritDoc} @@ -397,6 +411,7 @@ public class JavadocHelperTest { @since snc"""); } + @Test public void testMarkdown5() throws Exception { doTestJavadoc(""" ///[define classes][java.lang.invoke.MethodHandles.Lookup#defineClass(byte\\[\\])] @@ -417,6 +432,7 @@ public class JavadocHelperTest { @since snc"""); } + @Test public void testMarkdown6() throws Exception { doTestJavadoc(""" ///Text1 [define classes][java.lang.invoke.MethodHandles.Lookup#defineClass(byte\\[\\])] @@ -503,7 +519,7 @@ public class JavadocHelperTest { try (JavadocHelper helper = JavadocHelper.create(task, Arrays.asList(srcZip))) { String javadoc = helper.getResolvedDocComment(el); - assertEquals(javadoc, expectedJavadoc); + assertEquals(expectedJavadoc, javadoc); } } } @@ -547,6 +563,7 @@ public class JavadocHelperTest { * Set the system property `seed` to a random seed to reproduce * a specific run of this test. */ + @Test public void testRandomDocs() throws IOException { Random random = new Random(getSeed()); // Run test on 2% of classes, which corresponds to ~ 140 classes From 46b93a0aea0ac0ad7fa896eca5a43168c9da7ea8 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Tue, 10 Mar 2026 18:07:41 +0000 Subject: [PATCH 150/170] 8248165: Missing whitespace in jdb message printed when setting value of invalid type Reviewed-by: cjplummer --- .../classes/com/sun/tools/example/debug/expr/LValue.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/expr/LValue.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/expr/LValue.java index 3855d1bd51c..43b2c420147 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/expr/LValue.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/expr/LValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,11 +73,11 @@ abstract class LValue { setValue0(value); } catch (InvalidTypeException exc) { throw new ParseException( - "Attempt to set value of incorrect type" + + "Attempt to set value of incorrect type: " + exc); } catch (ClassNotLoadedException exc) { throw new ParseException( - "Attempt to set value before " + exc.className() + " was loaded" + + "Attempt to set value before " + exc.className() + " was loaded: " + exc); } } From 760f4b60434648fc723c84611a1a9c32d5915c91 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 10 Mar 2026 18:40:02 +0000 Subject: [PATCH 151/170] 8379344: Compact the Unicode/CLDR version tables Reviewed-by: alanb, jlu --- .../share/classes/java/lang/Character.java | 48 ++++++++++++++++--- .../java/util/spi/LocaleServiceProvider.java | 36 ++++++++++---- 2 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index 33284d86e2d..158c3126ab3 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -67,9 +67,13 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME; * Character information is based on the Unicode Standard, version 17.0. *

      * The Java platform has supported different versions of the Unicode - * Standard over time. Upgrades to newer versions of the Unicode Standard - * occurred in the following Java releases, each indicating the new version: + * Standard over time. The following tables list the version of Unicode used + * in each Java release. Unless otherwise specified, all update releases in a + * given Java release family use the same Unicode version. * + * * * * @@ -78,26 +82,56 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME; * * * + * + * + * + * + * + * + * + * + * + * + * + *
      Shows Java releases and supported Unicode versions
      Java release
      Java SE 26Unicode 17.0
      Java SE 25Unicode 16.0
      Java SE 21Unicode 15.0
      Java SE 17Unicode 13.0
      Java SE 11Unicode 10.0
      Java SE 8Unicode 6.2
      + *

      + * Show other Java releases + *

      Java releases prior to Java SE 8 are listed only if they upgraded the + * Unicode version

      + * + * + * + * + * + * + * * * + * + * * * * * * * + * + * + * + * * * + * + * * * * * - * - * + * + * * * - * - * * * * @@ -110,6 +144,8 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME; * * *
      Shows other Java releases and supported Unicode + * versions
      Java releaseUnicode version
      Java SE 24Unicode 16.0
      Java SE 23Unicode 15.1
      Java SE 22Unicode 15.1
      Java SE 20Unicode 15.0
      Java SE 19Unicode 14.0
      Java SE 18Unicode 13.0
      Java SE 16Unicode 13.0
      Java SE 15Unicode 13.0
      Java SE 14Unicode 12.1
      Java SE 13Unicode 12.1
      Java SE 12Unicode 11.0
      Java SE 11Unicode 10.0
      Java SE 10Unicode 8.0
      Java SE 9Unicode 8.0
      Java SE 8Unicode 6.2
      Java SE 7Unicode 6.0
      Java SE 5.0Unicode 1.1.5
      + *
      + *

      * Variations from these base Unicode versions, such as recognized appendixes, * are documented elsewhere. *

      Unicode Character Representations

      diff --git a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java index 5e7b61e6c57..abb9f3aca38 100644 --- a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java +++ b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -166,7 +166,7 @@ import java.util.Locale; * Common Locale Data Repository (CLDR) * to implement locale-sensitive APIs in the {@code java.util} and * {@code java.text} packages. This locale data derives the set of locales - * supported by the Java runtime environment. The following table lists the + * supported by the Java runtime environment. The following tables list the * version of CLDR used in each JDK release. Unless otherwise specified, all * update releases in a given JDK release family use the same CLDR version. * Note that the CLDR locale data are subject to change. Users should not assume @@ -175,6 +175,9 @@ import java.util.Locale; * Refer to CLDR Releases * for the deltas between their releases. * + * * * * @@ -185,22 +188,38 @@ import java.util.Locale; * * * + * + * + * + * + * + * + * + * + * + *
      JDK releases and supported CLDR versions
      JDK releaseCLDR 48
      JDK 25CLDR 47
      JDK 21CLDR 43
      JDK 17CLDR 39
      JDK 11CLDR 33
      JDK 8CLDR 21.0.1
      + *
      + * Show other JDK releases + * + * + * + * + * + * + * * * * * * * - * - * * * * * * * - * - * * * * @@ -211,16 +230,13 @@ import java.util.Locale; * * * - * - * * * * * - * - * * *
      Other JDK releases and supported CLDR + * versions
      JDK releaseCLDR version
      JDK 24CLDR 46
      JDK 23CLDR 45
      JDK 22CLDR 44
      JDK 21CLDR 43
      JDK 20CLDR 42
      JDK 19CLDR 41
      JDK 18CLDR 39
      JDK 17CLDR 39
      JDK 16CLDR 38
      JDK 15CLDR 35.1
      JDK 12CLDR 33
      JDK 11CLDR 33
      JDK 10CLDR 29
      JDK 9CLDR 29
      JDK 8CLDR 21.0.1
      + *
      * * @since 1.6 */ From 73b13f977bc3bd581883273508f54667b9fbfe5b Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Tue, 10 Mar 2026 18:44:23 +0000 Subject: [PATCH 152/170] 8378808: Refactor java/nio/Buffer TestNG tests to use JUnit Reviewed-by: alanb, liach --- test/jdk/java/nio/Buffer/BulkPutBuffer.java | 178 +++++++---------- test/jdk/java/nio/Buffer/ByteBufferViews.java | 87 +++++---- test/jdk/java/nio/Buffer/Chars.java | 30 +-- .../java/nio/Buffer/EqualsCompareTest.java | 184 ++++++++---------- .../jdk/java/nio/Buffer/ReachabilityTest.java | 19 +- .../java/nio/MappedByteBuffer/ForceViews.java | 106 +++++----- 6 files changed, 277 insertions(+), 327 deletions(-) diff --git a/test/jdk/java/nio/Buffer/BulkPutBuffer.java b/test/jdk/java/nio/Buffer/BulkPutBuffer.java index d1d10ebff87..85ebb624d0f 100644 --- a/test/jdk/java/nio/Buffer/BulkPutBuffer.java +++ b/test/jdk/java/nio/Buffer/BulkPutBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,18 +41,22 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.stream.Stream; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.function.Executable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 8219014 8245121 * @summary Ensure that a bulk put of a buffer into another is correct. * @compile BulkPutBuffer.java - * @run testng/othervm BulkPutBuffer + * @run junit/othervm BulkPutBuffer */ public class BulkPutBuffer { static final long SEED = System.nanoTime(); @@ -195,95 +199,64 @@ public class BulkPutBuffer { nextType = lookup.findVirtual(MyRandom.class, "next" + name, MethodType.methodType(elementType)); } catch (IllegalAccessException | NoSuchMethodException e) { - throw new AssertionError(e); + throw new RuntimeException(e); } } Buffer create(int capacity) throws Throwable { - Class bufferType = typeToAttr.get(elementType).type; + if (bufferType == ByteBuffer.class || kind == BufferKind.DIRECT || + kind == BufferKind.HEAP_VIEW) { - try { - if (bufferType == ByteBuffer.class || - kind == BufferKind.DIRECT || kind == BufferKind.HEAP_VIEW) { - int len = capacity*typeToAttr.get(elementType).bytes; - ByteBuffer bb = (ByteBuffer)allocBB.invoke(len); - byte[] bytes = new byte[len]; - RND.nextBytes(bytes); - bb.put(0, bytes); - if (bufferType == ByteBuffer.class) { - return (Buffer)bb; - } else { - bb.order(order); - return (Buffer)asTypeBuffer.invoke(bb); - } - } else if (bufferType == CharBuffer.class && - kind == BufferKind.STRING) { - char[] array = new char[capacity]; - for (int i = 0; i < capacity; i++) { - array[i] = RND.nextChar(); - } - return CharBuffer.wrap(new String(array)); + int len = capacity*typeToAttr.get(elementType).bytes; + ByteBuffer bb = (ByteBuffer)allocBB.invoke(len); + byte[] bytes = new byte[len]; + RND.nextBytes(bytes); + bb.put(0, bytes); + if (bufferType == ByteBuffer.class) { + return (Buffer)bb; } else { - Buffer buf = (Buffer)alloc.invoke(capacity); - for (int i = 0; i < capacity; i++) { - putAbs.invoke(buf, i, nextType.invoke(RND)); - } - return buf; + bb.order(order); + return (Buffer)asTypeBuffer.invoke(bb); } - } catch (Exception e) { - throw new AssertionError(e); + } else if (bufferType == CharBuffer.class && + kind == BufferKind.STRING) { + char[] array = new char[capacity]; + for (int i = 0; i < capacity; i++) { + array[i] = RND.nextChar(); + } + return CharBuffer.wrap(new String(array)); + } else { + Buffer buf = (Buffer)alloc.invoke(capacity); + for (int i = 0; i < capacity; i++) { + putAbs.invoke(buf, i, nextType.invoke(RND)); + } + return buf; } } void copy(Buffer src, int srcOff, Buffer dst, int dstOff, int length) throws Throwable { - try { - for (int i = 0; i < length; i++) { - putAbs.invoke(dst, dstOff + i, getAbs.invoke(src, srcOff + i)); - } - } catch (ReadOnlyBufferException ro) { - throw ro; - } catch (Exception e) { - throw new AssertionError(e); + for (int i = 0; i < length; i++) { + putAbs.invoke(dst, dstOff + i, getAbs.invoke(src, srcOff + i)); } } Buffer asReadOnlyBuffer(Buffer buf) throws Throwable { - try { - return (Buffer)asReadOnlyBuffer.invoke(buf); - } catch (Exception e) { - throw new AssertionError(e); - } + return (Buffer)asReadOnlyBuffer.invoke(buf); } void put(Buffer src, int srcOff, Buffer dst, int dstOff, int length) throws Throwable { - try { - putBufAbs.invoke(dst, dstOff, src, srcOff, length); - } catch (ReadOnlyBufferException ro) { - throw ro; - } catch (Exception e) { - throw new AssertionError(e); - } + putBufAbs.invoke(dst, dstOff, src, srcOff, length); } void put(Buffer src, Buffer dst) throws Throwable { - try { - putBufRel.invoke(dst, src); - } catch (ReadOnlyBufferException ro) { - throw ro; - } catch (Exception e) { - throw new AssertionError(e); - } + putBufRel.invoke(dst, src); } boolean equals(Buffer src, Buffer dst) throws Throwable { - try { - return Boolean.class.cast(equals.invoke(dst, src)); - } catch (Exception e) { - throw new AssertionError(e); - } + return Boolean.class.cast(equals.invoke(dst, src)); } } @@ -297,68 +270,58 @@ public class BulkPutBuffer { return proxies; } - @DataProvider - static Object[][] proxies() { - ArrayList args = new ArrayList<>(); + static Stream proxies() { + List args = new ArrayList(); for (Class type : typeToAttr.keySet()) { + List proxies = getProxies(type); for (BufferProxy proxy : proxies) { - args.add(new Object[] {proxy}); + args.add(proxy); } } - return args.toArray(Object[][]::new); + return args.stream(); } - @DataProvider - static Object[][] proxyPairs() { - List args = new ArrayList<>(); + static Stream proxyPairs() { + List args = new ArrayList(); for (Class type : typeToAttr.keySet()) { List proxies = getProxies(type); for (BufferProxy proxy1 : proxies) { for (BufferProxy proxy2 : proxies) { - args.add(new Object[] {proxy1, proxy2}); + args.add(Arguments.of(proxy1, proxy2)); } } } - return args.toArray(Object[][]::new); + return args.stream(); } - private static void expectThrows(Class exClass, Assert.ThrowingRunnable r) { - try { - r.run(); - } catch(Throwable e) { - if (e.getClass() != exClass && e.getCause().getClass() != exClass) { - throw new RuntimeException("Expected " + exClass + - "; got " + e.getCause().getClass(), e); - } - } - } - - @Test(dataProvider = "proxies") - public static void testExceptions(BufferProxy bp) throws Throwable { + @ParameterizedTest + @MethodSource("proxies") + public void testExceptions(BufferProxy bp) throws Throwable { int cap = 27; Buffer buf = bp.create(cap); - expectThrows(IndexOutOfBoundsException.class, + assertThrows(IndexOutOfBoundsException.class, () -> bp.put(buf, -1, buf, 0, 1)); - expectThrows(IndexOutOfBoundsException.class, + assertThrows(IndexOutOfBoundsException.class, () -> bp.put(buf, 0, buf, -1, 1)); - expectThrows(IndexOutOfBoundsException.class, + assertThrows(IndexOutOfBoundsException.class, () -> bp.put(buf, 1, buf, 0, cap)); - expectThrows(IndexOutOfBoundsException.class, + assertThrows(IndexOutOfBoundsException.class, () -> bp.put(buf, 0, buf, 1, cap)); - expectThrows(IndexOutOfBoundsException.class, + assertThrows(IndexOutOfBoundsException.class, () -> bp.put(buf, 0, buf, 0, cap + 1)); - expectThrows(IndexOutOfBoundsException.class, + assertThrows(IndexOutOfBoundsException.class, () -> bp.put(buf, 0, buf, 0, Integer.MAX_VALUE)); Buffer rob = buf.isReadOnly() ? buf : bp.asReadOnlyBuffer(buf); - expectThrows(ReadOnlyBufferException.class, + assertThrows(ReadOnlyBufferException.class, () -> bp.put(buf, 0, rob, 0, cap)); } - @Test(dataProvider = "proxies") - public static void testSelf(BufferProxy bp) throws Throwable { + @ParameterizedTest + @MethodSource("proxies") + public void testSelf(BufferProxy bp) throws Throwable { for (int i = 0; i < ITERATIONS; i++) { int cap = RND.nextInt(MAX_CAPACITY); Buffer buf = bp.create(cap); @@ -371,7 +334,7 @@ public class BulkPutBuffer { Buffer lowerCopy = bp.create(lowerLength); if (lowerCopy.isReadOnly()) { - Assert.expectThrows(ReadOnlyBufferException.class, + assertThrows(ReadOnlyBufferException.class, () -> bp.copy(lower, 0, lowerCopy, 0, lowerLength)); break; } @@ -385,7 +348,7 @@ public class BulkPutBuffer { bp.put(lower, middle); middle.flip(); - Assert.assertTrue(bp.equals(lowerCopy, middle), + assertTrue(bp.equals(lowerCopy, middle), String.format("%d %s %d %d %d %d%n", SEED, buf.getClass().getName(), cap, lowerOffset, lowerLength, middleOffset)); @@ -395,15 +358,16 @@ public class BulkPutBuffer { bp.put(buf, lowerOffset, buf, middleOffset, lowerLength); - Assert.assertTrue(bp.equals(lowerCopy, middle), + assertTrue(bp.equals(lowerCopy, middle), String.format("%d %s %d %d %d %d%n", SEED, buf.getClass().getName(), cap, lowerOffset, lowerLength, middleOffset)); } } - @Test(dataProvider = "proxyPairs") - public static void testPairs(BufferProxy bp, BufferProxy sbp) throws Throwable { + @ParameterizedTest + @MethodSource("proxyPairs") + public void testPairs(BufferProxy bp, BufferProxy sbp) throws Throwable { for (int i = 0; i < ITERATIONS; i++) { int cap = Math.max(4, RND.nextInt(MAX_CAPACITY)); int cap2 = cap/2; @@ -426,7 +390,7 @@ public class BulkPutBuffer { src.limit(slim); if (buf.isReadOnly()) { - Assert.expectThrows(ReadOnlyBufferException.class, + assertThrows(ReadOnlyBufferException.class, () -> bp.put(src, buf)); break; } @@ -438,7 +402,7 @@ public class BulkPutBuffer { buf.reset(); src.reset(); - Assert.assertTrue(bp.equals(src, buf), + assertTrue(bp.equals(src, buf), String.format("%d %s %d %d %d %s %d %d %d%n", SEED, buf.getClass().getName(), cap, pos, lim, src.getClass().getName(), scap, spos, slim)); @@ -452,7 +416,7 @@ public class BulkPutBuffer { buf.position(pos); buf.limit(lim); - Assert.assertTrue(bp.equals(src, buf), + assertTrue(bp.equals(src, buf), String.format("%d %s %d %d %d %s %d %d %d%n", SEED, buf.getClass().getName(), cap, pos, lim, src.getClass().getName(), scap, spos, slim)); diff --git a/test/jdk/java/nio/Buffer/ByteBufferViews.java b/test/jdk/java/nio/Buffer/ByteBufferViews.java index f0136939d53..17bd6af4033 100644 --- a/test/jdk/java/nio/Buffer/ByteBufferViews.java +++ b/test/jdk/java/nio/Buffer/ByteBufferViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,9 @@ /* @test * @summary Binary data and view tests for byte buffers * @bug 8159257 8258955 - * @run testng ByteBufferViews + * @run junit ByteBufferViews */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -46,8 +43,15 @@ import java.util.function.IntFunction; import java.util.function.IntUnaryOperator; import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import java.util.stream.Stream; -import static org.testng.Assert.*; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.fail; public class ByteBufferViews { static final int SIZE = 32; @@ -127,14 +131,15 @@ public class ByteBufferViews { // Creates a cross product of test arguments for // buffer allocator functions and buffer view functions - static Object[][] product(List> la, - List> lb) { + static Stream product(List> la, + List> lb) { return la.stream().flatMap(lae -> lb.stream(). - map(lbe -> List.of( - lae.getKey() + " -> " + lbe.getKey(), - lae.getValue(), - lbe.getValue()).toArray() - )).toArray(Object[][]::new); + map(lbe -> Arguments.of + ( + lae.getKey() + " -> " + lbe.getKey(), + lae.getValue(), + lbe.getValue()) + )); } static void assertValues(int i, Object bValue, Object bbValue, ByteBuffer bb) { @@ -167,8 +172,7 @@ public class ByteBufferViews { } - @DataProvider - public static Object[][] shortViewProvider() { + public static Stream shortBufferViews() { List>> bfs = List.of( Map.entry("bb.asShortBuffer()", bb -> bb.asShortBuffer()), @@ -186,7 +190,8 @@ public class ByteBufferViews { return product(BYTE_BUFFER_FUNCTIONS, bfs); } - @Test(dataProvider = "shortViewProvider") + @ParameterizedTest + @MethodSource("shortBufferViews") public void testShortGet(String desc, IntFunction fbb, Function fbi) { ByteBuffer bb = allocate(fbb); @@ -213,7 +218,8 @@ public class ByteBufferViews { } - @Test(dataProvider = "shortViewProvider") + @ParameterizedTest + @MethodSource("shortBufferViews") public void testShortPut(String desc, IntFunction fbb, Function fbi) { ByteBuffer bbfilled = allocate(fbb); @@ -271,8 +277,7 @@ public class ByteBufferViews { } } - @DataProvider - public static Object[][] charViewProvider() { + public static Stream charBufferViews() { List>> bfs = List.of( Map.entry("bb.asCharBuffer()", bb -> bb.asCharBuffer()), @@ -290,7 +295,8 @@ public class ByteBufferViews { return product(BYTE_BUFFER_FUNCTIONS, bfs); } - @Test(dataProvider = "charViewProvider") + @ParameterizedTest + @MethodSource("charBufferViews") public void testCharGet(String desc, IntFunction fbb, Function fbi) { ByteBuffer bb = allocate(fbb); @@ -317,7 +323,8 @@ public class ByteBufferViews { } - @Test(dataProvider = "charViewProvider") + @ParameterizedTest + @MethodSource("charBufferViews") public void testCharPut(String desc, IntFunction fbb, Function fbi) { ByteBuffer bbfilled = allocate(fbb); @@ -368,8 +375,7 @@ public class ByteBufferViews { } - @DataProvider - public static Object[][] intViewProvider() { + public static Stream intBufferViews() { List>> bfs = List.of( Map.entry("bb.asIntBuffer()", bb -> bb.asIntBuffer()), @@ -387,7 +393,8 @@ public class ByteBufferViews { return product(BYTE_BUFFER_FUNCTIONS, bfs); } - @Test(dataProvider = "intViewProvider") + @ParameterizedTest + @MethodSource("intBufferViews") public void testIntGet(String desc, IntFunction fbb, Function fbi) { ByteBuffer bb = allocate(fbb); @@ -414,7 +421,8 @@ public class ByteBufferViews { } - @Test(dataProvider = "intViewProvider") + @ParameterizedTest + @MethodSource("intBufferViews") public void testIntPut(String desc, IntFunction fbb, Function fbi) { ByteBuffer bbfilled = allocate(fbb); @@ -475,8 +483,7 @@ public class ByteBufferViews { } - @DataProvider - public static Object[][] longViewProvider() { + public static Stream longBufferViews() { List>> bfs = List.of( Map.entry("bb.asLongBuffer()", bb -> bb.asLongBuffer()), @@ -494,7 +501,8 @@ public class ByteBufferViews { return product(BYTE_BUFFER_FUNCTIONS, bfs); } - @Test(dataProvider = "longViewProvider") + @ParameterizedTest + @MethodSource("longBufferViews") public void testLongGet(String desc, IntFunction fbb, Function fbi) { ByteBuffer bb = allocate(fbb); @@ -521,7 +529,8 @@ public class ByteBufferViews { } - @Test(dataProvider = "longViewProvider") + @ParameterizedTest + @MethodSource("longBufferViews") public void testLongPut(String desc, IntFunction fbb, Function fbi) { ByteBuffer bbfilled = allocate(fbb); @@ -587,9 +596,7 @@ public class ByteBufferViews { } } - - @DataProvider - public static Object[][] floatViewProvider() { + public static Stream floatBufferViews() { List>> bfs = List.of( Map.entry("bb.asFloatBuffer()", bb -> bb.asFloatBuffer()), @@ -607,7 +614,8 @@ public class ByteBufferViews { return product(BYTE_BUFFER_FUNCTIONS, bfs); } - @Test(dataProvider = "floatViewProvider") + @ParameterizedTest + @MethodSource("floatBufferViews") public void testFloatGet(String desc, IntFunction fbb, Function fbi) { ByteBuffer bb = allocate(fbb); @@ -634,7 +642,8 @@ public class ByteBufferViews { } - @Test(dataProvider = "floatViewProvider") + @ParameterizedTest + @MethodSource("floatBufferViews") public void testFloatPut(String desc, IntFunction fbb, Function fbi) { ByteBuffer bbfilled = allocate(fbb); @@ -684,10 +693,7 @@ public class ByteBufferViews { return Float.intBitsToFloat(getIntFromBytes(bb, i)); } - - - @DataProvider - public static Object[][] doubleViewProvider() { + public static Stream doubleBufferViews() { List>> bfs = List.of( Map.entry("bb.asDoubleBuffer()", bb -> bb.asDoubleBuffer()), @@ -705,7 +711,7 @@ public class ByteBufferViews { return product(BYTE_BUFFER_FUNCTIONS, bfs); } - @Test(dataProvider = "doubleViewProvider") + @MethodSource("doubleBufferViews") public void testDoubleGet(String desc, IntFunction fbb, Function fbi) { ByteBuffer bb = allocate(fbb); @@ -732,7 +738,8 @@ public class ByteBufferViews { } - @Test(dataProvider = "doubleViewProvider") + @ParameterizedTest + @MethodSource("doubleBufferViews") public void testDoublePut(String desc, IntFunction fbb, Function fbi) { ByteBuffer bbfilled = allocate(fbb); diff --git a/test/jdk/java/nio/Buffer/Chars.java b/test/jdk/java/nio/Buffer/Chars.java index 01b53ea2405..1b978eecb74 100644 --- a/test/jdk/java/nio/Buffer/Chars.java +++ b/test/jdk/java/nio/Buffer/Chars.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8014854 * @summary Exercises CharBuffer#chars on each of the CharBuffer types - * @run testng Chars + * @run junit Chars * @key randomness */ @@ -35,11 +35,13 @@ import java.nio.CharBuffer; import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.stream.Stream; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class Chars { @@ -98,8 +100,7 @@ public class Chars { buffers.add(randomizeRange(cb.asReadOnlyBuffer())); } - @DataProvider(name = "charbuffers") - public Object[][] createCharBuffers() { + private static Stream createCharBuffers() { List buffers = new ArrayList<>(); // heap @@ -119,20 +120,21 @@ public class Chars { // read-only buffer backed by a CharSequence buffers.add(CharBuffer.wrap(randomize(CharBuffer.allocate(SIZE)))); - Object[][] params = new Object[buffers.size()][]; + List params = new ArrayList(); for (int i = 0; i < buffers.size(); i++) { CharBuffer cb = buffers.get(i); - params[i] = new Object[] { cb.getClass().getName(), cb }; + params.add((Arguments.of(cb.getClass().getName(), cb))); } - return params; + return params.stream(); } - @Test(dataProvider = "charbuffers") + @ParameterizedTest + @MethodSource("createCharBuffers") public void testChars(String type, CharBuffer cb) { - System.out.format("%s position=%d, limit=%d%n", type, cb.position(), cb.limit()); + System.err.format("%s position=%d, limit=%d%n", type, cb.position(), cb.limit()); int expected = intSum(cb); - assertEquals(cb.chars().sum(), expected); - assertEquals(cb.chars().parallel().sum(), expected); + assertEquals(expected, cb.chars().sum()); + assertEquals(expected, cb.chars().parallel().sum()); } } diff --git a/test/jdk/java/nio/Buffer/EqualsCompareTest.java b/test/jdk/java/nio/Buffer/EqualsCompareTest.java index 03bd7c26a58..8c098767253 100644 --- a/test/jdk/java/nio/Buffer/EqualsCompareTest.java +++ b/test/jdk/java/nio/Buffer/EqualsCompareTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,10 +21,6 @@ * questions. */ -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -48,15 +44,25 @@ import java.util.Set; import java.util.function.BiFunction; import java.util.function.LongFunction; import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.StandardOpenOption.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 8193085 8199773 * @summary tests for buffer equals and compare - * @run testng EqualsCompareTest + * @run junit EqualsCompareTest */ public class EqualsCompareTest { @@ -446,89 +452,66 @@ public class EqualsCompareTest { } } - static Object[][] bufferTypes; - - @DataProvider - public static Object[][] bufferTypesProvider() { - if (bufferTypes == null) { - bufferTypes = new Object[][]{ - {new BufferType.Bytes(BufferKind.HEAP)}, - {new BufferType.Bytes(BufferKind.DIRECT)}, - {new BufferType.Chars(BufferKind.HEAP)}, - {new BufferType.Chars(BufferKind.HEAP_VIEW)}, - {new BufferType.Chars(BufferKind.DIRECT)}, - {new BufferType.Shorts(BufferKind.HEAP)}, - {new BufferType.Shorts(BufferKind.HEAP_VIEW)}, - {new BufferType.Shorts(BufferKind.DIRECT)}, - {new BufferType.Ints(BufferKind.HEAP)}, - {new BufferType.Ints(BufferKind.HEAP_VIEW)}, - {new BufferType.Ints(BufferKind.DIRECT)}, - {new BufferType.Floats(BufferKind.HEAP)}, - {new BufferType.Floats(BufferKind.HEAP_VIEW)}, - {new BufferType.Floats(BufferKind.DIRECT)}, - {new BufferType.Longs(BufferKind.HEAP)}, - {new BufferType.Longs(BufferKind.HEAP_VIEW)}, - {new BufferType.Longs(BufferKind.DIRECT)}, - {new BufferType.Doubles(BufferKind.HEAP)}, - {new BufferType.Doubles(BufferKind.HEAP_VIEW)}, - {new BufferType.Doubles(BufferKind.DIRECT)}, - }; - } - return bufferTypes; + public static Stream bufferTypesSource() { + return Stream.of + (new BufferType.Bytes(BufferKind.HEAP), + new BufferType.Bytes(BufferKind.DIRECT), + new BufferType.Chars(BufferKind.HEAP), + new BufferType.Chars(BufferKind.HEAP_VIEW), + new BufferType.Chars(BufferKind.DIRECT), + new BufferType.Shorts(BufferKind.HEAP), + new BufferType.Shorts(BufferKind.HEAP_VIEW), + new BufferType.Shorts(BufferKind.DIRECT), + new BufferType.Ints(BufferKind.HEAP), + new BufferType.Ints(BufferKind.HEAP_VIEW), + new BufferType.Ints(BufferKind.DIRECT), + new BufferType.Floats(BufferKind.HEAP), + new BufferType.Floats(BufferKind.HEAP_VIEW), + new BufferType.Floats(BufferKind.DIRECT), + new BufferType.Longs(BufferKind.HEAP), + new BufferType.Longs(BufferKind.HEAP_VIEW), + new BufferType.Longs(BufferKind.DIRECT), + new BufferType.Doubles(BufferKind.HEAP), + new BufferType.Doubles(BufferKind.HEAP_VIEW), + new BufferType.Doubles(BufferKind.DIRECT)); } - - static Object[][] floatbufferTypes; - - @DataProvider - public static Object[][] floatBufferTypesProvider() { - if (floatbufferTypes == null) { + public static Stream floatBufferTypesSource() { LongFunction bTof = rb -> Float.intBitsToFloat((int) rb); LongFunction bToD = Double::longBitsToDouble; - floatbufferTypes = new Object[][]{ - // canonical and non-canonical NaNs - // If conversion is a signalling NaN it may be subject to conversion to a - // quiet NaN on some processors, even if a copy is performed - // The tests assume that if conversion occurs it does not convert to the - // canonical NaN - new Object[]{new BufferType.Floats(BufferKind.HEAP), 0x7fc00000L, 0x7f800001L, bTof}, - new Object[]{new BufferType.Floats(BufferKind.HEAP_VIEW), 0x7fc00000L, 0x7f800001L, bTof}, - new Object[]{new BufferType.Floats(BufferKind.DIRECT), 0x7fc00000L, 0x7f800001L, bTof}, - new Object[]{new BufferType.Doubles(BufferKind.HEAP), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD}, - new Object[]{new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD}, - new Object[]{new BufferType.Doubles(BufferKind.DIRECT), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD}, + return Stream.of + (// canonical and non-canonical NaNs + // If conversion is a signalling NaN it may be subject to conversion to a + // quiet NaN on some processors, even if a copy is performed + // The tests assume that if conversion occurs it does not convert to the + // canonical NaN + Arguments.of(new BufferType.Floats(BufferKind.HEAP), 0x7fc00000L, 0x7f800001L, bTof), + Arguments.of(new BufferType.Floats(BufferKind.HEAP_VIEW), 0x7fc00000L, 0x7f800001L, bTof), + Arguments.of(new BufferType.Floats(BufferKind.DIRECT), 0x7fc00000L, 0x7f800001L, bTof), + Arguments.of(new BufferType.Doubles(BufferKind.HEAP), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD), + Arguments.of(new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD), + Arguments.of(new BufferType.Doubles(BufferKind.DIRECT), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD), - // +0.0 and -0.0 - new Object[]{new BufferType.Floats(BufferKind.HEAP), 0x0L, 0x80000000L, bTof}, - new Object[]{new BufferType.Floats(BufferKind.HEAP_VIEW), 0x0L, 0x80000000L, bTof}, - new Object[]{new BufferType.Floats(BufferKind.DIRECT), 0x0L, 0x80000000L, bTof}, - new Object[]{new BufferType.Doubles(BufferKind.HEAP), 0x0L, 0x8000000000000000L, bToD}, - new Object[]{new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x0L, 0x8000000000000000L, bToD}, - new Object[]{new BufferType.Doubles(BufferKind.DIRECT), 0x0L, 0x8000000000000000L, bToD}, - }; - } - return floatbufferTypes; + // +0.0 and -0.0 + Arguments.of(new BufferType.Floats(BufferKind.HEAP), 0x0L, 0x80000000L, bTof), + Arguments.of(new BufferType.Floats(BufferKind.HEAP_VIEW), 0x0L, 0x80000000L, bTof), + Arguments.of(new BufferType.Floats(BufferKind.DIRECT), 0x0L, 0x80000000L, bTof), + Arguments.of(new BufferType.Doubles(BufferKind.HEAP), 0x0L, 0x8000000000000000L, bToD), + Arguments.of(new BufferType.Doubles(BufferKind.HEAP_VIEW), 0x0L, 0x8000000000000000L, bToD), + Arguments.of(new BufferType.Doubles(BufferKind.DIRECT), 0x0L, 0x8000000000000000L, bToD)); } - - static Object[][] charBufferTypes; - - @DataProvider - public static Object[][] charBufferTypesProvider() { - if (charBufferTypes == null) { - charBufferTypes = new Object[][]{ - {new BufferType.Chars(BufferKind.HEAP)}, - {new BufferType.Chars(BufferKind.HEAP_VIEW)}, - {new BufferType.Chars(BufferKind.DIRECT)}, - }; - } - return charBufferTypes; + public static Stream charBufferTypesSource() { + return Stream.of + (Arguments.of(new BufferType.Chars(BufferKind.HEAP)), + Arguments.of(new BufferType.Chars(BufferKind.HEAP_VIEW)), + Arguments.of(new BufferType.Chars(BufferKind.DIRECT))); } - // Tests all primitive buffers - @Test(dataProvider = "bufferTypesProvider") + @ParameterizedTest + @MethodSource("bufferTypesSource") void testBuffers(BufferType bufferType) { // Test with buffers of the same byte order (BE) @@ -559,7 +542,8 @@ public class EqualsCompareTest { } // Tests float and double buffers with edge-case values (NaN, -0.0, +0.0) - @Test(dataProvider = "floatBufferTypesProvider") + @ParameterizedTest + @MethodSource("floatBufferTypesSource") public void testFloatBuffers( BufferType bufferType, long rawBitsA, long rawBitsB, @@ -596,17 +580,18 @@ public class EqualsCompareTest { // Sanity check int size = arraySizeFor(bufferType.elementType); - Assert.assertTrue(bufferType.pairWiseEquals(allAs.apply(bufferType, size), - allBs.apply(bufferType, size))); - Assert.assertTrue(bufferType.equals(allAs.apply(bufferType, size), - allBs.apply(bufferType, size))); + assertTrue(bufferType.pairWiseEquals(allAs.apply(bufferType, size), + allBs.apply(bufferType, size))); + assertTrue(bufferType.equals(allAs.apply(bufferType, size), + allBs.apply(bufferType, size))); testBufferType(bufferType, allAs, allBs); testBufferType(bufferType, allAs, halfBs); } // Tests CharBuffer for region sources and CharSequence sources - @Test(dataProvider = "charBufferTypesProvider") + @ParameterizedTest + @MethodSource("charBufferTypesSource") public void testCharBuffers(BufferType.Chars charBufferType) { BiFunction constructor = (at, s) -> { @@ -623,7 +608,6 @@ public class EqualsCompareTest { testBufferType(charBufferType, constructor, constructorX); } - > void testBufferType(BT bt, BiFunction aConstructor, @@ -652,26 +636,26 @@ public class EqualsCompareTest { : b; boolean eq = bt.pairWiseEquals(as, bs); - Assert.assertEquals(bt.equals(as, bs), eq); - Assert.assertEquals(bt.equals(bs, as), eq); + assertEquals(eq, bt.equals(as, bs)); + assertEquals(eq, bt.equals(bs, as)); if (eq) { - Assert.assertEquals(bt.compare(as, bs), 0); - Assert.assertEquals(bt.compare(bs, as), 0); + assertEquals(0, bt.compare(as, bs)); + assertEquals(0, bt.compare(bs, as)); // If buffers are equal, there shall be no mismatch - Assert.assertEquals(bt.mismatch(as, bs), -1); - Assert.assertEquals(bt.mismatch(bs, as), -1); + assertEquals(-1, bt.mismatch(as, bs)); + assertEquals(-1, bt.mismatch(bs, as)); } else { int aCb = bt.compare(as, bs); int bCa = bt.compare(bs, as); int v = Integer.signum(aCb) * Integer.signum(bCa); - Assert.assertTrue(v == -1); + assertEquals(-1, v); int aMs = bt.mismatch(as, bs); int bMs = bt.mismatch(bs, as); - Assert.assertNotEquals(aMs, -1); - Assert.assertEquals(aMs, bMs); + assertNotEquals(-1, aMs); + assertEquals(bMs, aMs); } } } @@ -686,17 +670,17 @@ public class EqualsCompareTest { // Create common prefix with a length of i - aFrom bt.set(c, i, -1); - Assert.assertFalse(bt.equals(c, a)); + assertFalse(bt.equals(c, a)); int cCa = bt.compare(cs, as); int aCc = bt.compare(as, cs); int v = Integer.signum(cCa) * Integer.signum(aCc); - Assert.assertTrue(v == -1); + assertEquals(-1, v); int cMa = bt.mismatch(cs, as); int aMc = bt.mismatch(as, cs); - Assert.assertEquals(cMa, aMc); - Assert.assertEquals(cMa, i - aFrom); + assertEquals(aMc, cMa); + assertEquals(i - aFrom, cMa); } } } @@ -731,8 +715,8 @@ public class EqualsCompareTest { try (FileChannel fc = FileChannel.open(path, READ, DELETE_ON_CLOSE)) { MappedByteBuffer one = fc.map(FileChannel.MapMode.READ_ONLY, 0, bytes.length); ByteBuffer two = ByteBuffer.wrap(bytes); - Assert.assertEquals(one, two); - Assert.assertEquals(one.hashCode(), two.hashCode()); + assertEquals(two, one); + assertEquals(two.hashCode(), one.hashCode()); } } } diff --git a/test/jdk/java/nio/Buffer/ReachabilityTest.java b/test/jdk/java/nio/Buffer/ReachabilityTest.java index 2b0a2710b46..114077b3626 100644 --- a/test/jdk/java/nio/Buffer/ReachabilityTest.java +++ b/test/jdk/java/nio/Buffer/ReachabilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,9 @@ /* @test * @bug 8208362 * @summary Tests reachability from source to dependent direct byte buffers - * @run testng ReachabilityTest + * @run junit ReachabilityTest */ -import org.testng.Assert; -import org.testng.annotations.Test; - import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; @@ -41,8 +38,14 @@ import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.function.UnaryOperator; +import org.junit.jupiter.api.Test; + import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + public class ReachabilityTest { @Test @@ -98,13 +101,13 @@ public class ReachabilityTest { } } } catch (InterruptedException unexpected) { - throw new AssertionError("unexpected InterruptedException"); + fail("unexpected InterruptedException"); } // Some or all of the intermediate values must be GC'ed - Assert.assertTrue(collected); + assertTrue(collected); // The root should never be GC'ed - Assert.assertNotNull(root.get()); + assertNotNull(root.get()); Reference.reachabilityFence(t); } diff --git a/test/jdk/java/nio/MappedByteBuffer/ForceViews.java b/test/jdk/java/nio/MappedByteBuffer/ForceViews.java index 57ddac28cdf..950b35dc0c3 100644 --- a/test/jdk/java/nio/MappedByteBuffer/ForceViews.java +++ b/test/jdk/java/nio/MappedByteBuffer/ForceViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,46 +25,31 @@ * @test * @bug 4833719 * @summary Verify MappedByteBuffer force on compact, duplicate, and slice views - * @run testng ForceViews + * @run junit ForceViews */ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.ReadOnlyBufferException; import java.nio.channels.FileChannel; -import static java.nio.channels.FileChannel.MapMode.*; import java.nio.file.Path; -import static java.nio.file.StandardOpenOption.*; import java.util.function.BiFunction; +import java.util.stream.Stream; -import org.testng.Assert; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static java.nio.channels.FileChannel.MapMode.*; +import static java.nio.file.StandardOpenOption.*; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; public class ForceViews { static record Segment(int position, int length) {} - private FileChannel fc; - - @BeforeTest(alwaysRun=true) - public void openChannel() throws IOException { - Path file = Path.of(".", "junk"); - fc = FileChannel.open(file, CREATE_NEW, READ, WRITE, DELETE_ON_CLOSE); - ByteBuffer buf = ByteBuffer.wrap(new byte[1024]); - fc.write(buf); - fc.position(0); - } - - @AfterTest(alwaysRun=true) - public void closeChannel() throws IOException { - fc.close(); - } - - @DataProvider - public Object[][] provider() throws IOException { + public static Stream provider() throws IOException { BiFunction absSlice = (m, s) -> { return m.slice(s.position, s.length); }; BiFunction relSlice = @@ -75,42 +60,47 @@ public class ForceViews { BiFunction compact = (m, s) -> { return m.compact(); }; - Object[][] result = new Object[][] { - {"Absolute slice", fc, 256, 512, 128, 128, 32, 32, absSlice}, - {"Relative slice", fc, 256, 512, 0, 128, 32, 32, relSlice}, - {"Duplicate", fc, 256, 512, 0, 256, 32, 32, duplicate}, - {"Compact", fc, 256, 512, 0, 256, 32, 32, compact} - }; - - return result; + return Stream.of + (Arguments.of("Absolute slice", 256, 512, 128, 128, 32, 32, absSlice), + Arguments.of("Relative slice", 256, 512, 0, 128, 32, 32, relSlice), + Arguments.of("Duplicate", 256, 512, 0, 256, 32, 32, duplicate), + Arguments.of("Compact", 256, 512, 0, 256, 32, 32, compact)); } - @Test(dataProvider = "provider") - public void test(String tst, FileChannel fc, int mapPosition, int mapLength, - int sliceIndex, int sliceLength, int regionOffset, int regionLength, - BiFunction f) + @ParameterizedTest + @MethodSource("provider") + public void test(String tst, int mapPosition, int mapLength, + int sliceIndex, int sliceLength, int regionOffset, + int regionLength, + BiFunction f) throws Exception { - MappedByteBuffer mbb = fc.map(READ_WRITE, mapPosition, mapLength); - mbb = f.apply(mbb, new Segment(sliceIndex, sliceLength)); - for (int i = regionOffset; i < regionOffset + regionLength; i++) { - mbb.put(i, (byte)i); - } - mbb.force(regionOffset, regionOffset + regionLength); - int fcPos = mapPosition + sliceIndex + regionOffset; - int mbbPos = regionOffset; - int length = regionLength; + Path file = Path.of(".", "junk"); + try (FileChannel fc = FileChannel.open(file, CREATE, READ, WRITE, DELETE_ON_CLOSE)) { + fc.write(ByteBuffer.wrap(new byte[1024])); + fc.position(0); - ByteBuffer buf = ByteBuffer.allocate(length); - fc.position(fcPos); - fc.read(buf); - for (int i = 0; i < length; i++) { - int fcVal = buf.get(i); - int mbbVal = mbb.get(mbbPos + i); - int val = regionOffset + i; - Assert.assertTrue(fcVal == val && mbbVal == val, - String.format("%s: i %d, fcVal %d, mbbVal %d, val %d", - tst, i, fcVal, mbbVal, val)); + MappedByteBuffer mbb = fc.map(READ_WRITE, mapPosition, mapLength); + mbb = f.apply(mbb, new Segment(sliceIndex, sliceLength)); + for (int i = regionOffset; i < regionOffset + regionLength; i++) { + mbb.put(i, (byte)i); + } + mbb.force(regionOffset, regionOffset + regionLength); + + int fcPos = mapPosition + sliceIndex + regionOffset; + int mbbPos = regionOffset; + int length = regionLength; + + ByteBuffer buf = ByteBuffer.allocate(length); + fc.position(fcPos); + fc.read(buf); + for (int i = 0; i < length; i++) { + int fcVal = buf.get(i); + int mbbVal = mbb.get(mbbPos + i); + int val = regionOffset + i; + assertEquals(val, fcVal); + assertEquals(val, mbbVal); + } } } } From b9220c930a6e2b3de1fcfab97e09252310b3ff39 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 10 Mar 2026 19:08:08 +0000 Subject: [PATCH 153/170] 8379552: Correct build tags in StrictMath/PowTests.java Reviewed-by: bpb --- test/jdk/java/lang/StrictMath/PowTests.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/lang/StrictMath/PowTests.java b/test/jdk/java/lang/StrictMath/PowTests.java index 4b68c5bdcd6..90482b264fe 100644 --- a/test/jdk/java/lang/StrictMath/PowTests.java +++ b/test/jdk/java/lang/StrictMath/PowTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,9 @@ /* * @test * @bug 8136874 8362376 + * @build Tests + * @build PowTests + * @run main PowTests * @summary Tests for StrictMath.pow */ From e00d6d28e19f73146223154d4061fbec10107bd9 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 10 Mar 2026 19:15:27 +0000 Subject: [PATCH 154/170] 8378899: Remove AppContext from java.awt.Toolkit implementation Reviewed-by: dnguyen, serb --- .../share/classes/java/awt/Toolkit.java | 45 +++---------------- 1 file changed, 6 insertions(+), 39 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/Toolkit.java b/src/java.desktop/share/classes/java/awt/Toolkit.java index 1ca5cdd8112..4fc9dc8e82d 100644 --- a/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,6 @@ import java.util.stream.Collectors; import javax.accessibility.AccessibilityProvider; import sun.awt.AWTAccessor; -import sun.awt.AppContext; import sun.awt.HeadlessToolkit; import sun.awt.PeerEvent; import sun.awt.PlatformGraphicsInfo; @@ -2046,8 +2045,6 @@ public abstract class Toolkit { @SuppressWarnings("serial") private static class DesktopPropertyChangeSupport extends PropertyChangeSupport { - private static final StringBuilder PROP_CHANGE_SUPPORT_KEY = - new StringBuilder("desktop property change support key"); private final Object source; public DesktopPropertyChangeSupport(Object sourceBean) { @@ -2055,16 +2052,14 @@ public abstract class Toolkit { source = sourceBean; } + private static PropertyChangeSupport pcs; @Override public synchronized void addPropertyChangeListener( String propertyName, PropertyChangeListener listener) { - PropertyChangeSupport pcs = (PropertyChangeSupport) - AppContext.getAppContext().get(PROP_CHANGE_SUPPORT_KEY); if (null == pcs) { pcs = new PropertyChangeSupport(source); - AppContext.getAppContext().put(PROP_CHANGE_SUPPORT_KEY, pcs); } pcs.addPropertyChangeListener(propertyName, listener); } @@ -2074,8 +2069,6 @@ public abstract class Toolkit { String propertyName, PropertyChangeListener listener) { - PropertyChangeSupport pcs = (PropertyChangeSupport) - AppContext.getAppContext().get(PROP_CHANGE_SUPPORT_KEY); if (null != pcs) { pcs.removePropertyChangeListener(propertyName, listener); } @@ -2084,8 +2077,6 @@ public abstract class Toolkit { @Override public synchronized PropertyChangeListener[] getPropertyChangeListeners() { - PropertyChangeSupport pcs = (PropertyChangeSupport) - AppContext.getAppContext().get(PROP_CHANGE_SUPPORT_KEY); if (null != pcs) { return pcs.getPropertyChangeListeners(); } else { @@ -2096,8 +2087,6 @@ public abstract class Toolkit { @Override public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { - PropertyChangeSupport pcs = (PropertyChangeSupport) - AppContext.getAppContext().get(PROP_CHANGE_SUPPORT_KEY); if (null != pcs) { return pcs.getPropertyChangeListeners(propertyName); } else { @@ -2107,19 +2096,14 @@ public abstract class Toolkit { @Override public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { - PropertyChangeSupport pcs = (PropertyChangeSupport) - AppContext.getAppContext().get(PROP_CHANGE_SUPPORT_KEY); if (null == pcs) { pcs = new PropertyChangeSupport(source); - AppContext.getAppContext().put(PROP_CHANGE_SUPPORT_KEY, pcs); } pcs.addPropertyChangeListener(listener); } @Override public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { - PropertyChangeSupport pcs = (PropertyChangeSupport) - AppContext.getAppContext().get(PROP_CHANGE_SUPPORT_KEY); if (null != pcs) { pcs.removePropertyChangeListener(listener); } @@ -2131,33 +2115,16 @@ public abstract class Toolkit { */ @Override public void firePropertyChange(final PropertyChangeEvent evt) { + if (pcs == null) { + return; + } Object oldValue = evt.getOldValue(); Object newValue = evt.getNewValue(); String propertyName = evt.getPropertyName(); if (oldValue != null && newValue != null && oldValue.equals(newValue)) { return; } - Runnable updater = new Runnable() { - public void run() { - PropertyChangeSupport pcs = (PropertyChangeSupport) - AppContext.getAppContext().get(PROP_CHANGE_SUPPORT_KEY); - if (null != pcs) { - pcs.firePropertyChange(evt); - } - } - }; - final AppContext currentAppContext = AppContext.getAppContext(); - for (AppContext appContext : AppContext.getAppContexts()) { - if (null == appContext || appContext.isDisposed()) { - continue; - } - if (currentAppContext == appContext) { - updater.run(); - } else { - final PeerEvent e = new PeerEvent(source, updater, PeerEvent.ULTIMATE_PRIORITY_EVENT); - SunToolkit.postEvent(appContext, e); - } - } + pcs.firePropertyChange(evt); } } From 08c0a787686df205f5a2d12b5b23b2a97f155090 Mon Sep 17 00:00:00 2001 From: Matias Saavedra Silva Date: Tue, 10 Mar 2026 20:48:52 +0000 Subject: [PATCH 155/170] 8378371: Default classlist not deterministic due to JIT activity Reviewed-by: rriggs, liach, erikj --- make/GenerateLinkOptData.gmk | 4 + .../runtime/cds/DeterministicClasslist.java | 111 ++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 test/hotspot/jtreg/runtime/cds/DeterministicClasslist.java diff --git a/make/GenerateLinkOptData.gmk b/make/GenerateLinkOptData.gmk index 6f6e1f29b4c..d615a34e71a 100644 --- a/make/GenerateLinkOptData.gmk +++ b/make/GenerateLinkOptData.gmk @@ -70,12 +70,15 @@ CLASSLIST_FILE_VM_OPTS = \ # Save the stderr output of the command and print it along with stdout in case # something goes wrong. +# The classlists must be generated with -Xint to avoid non-determinism +# introduced by JIT compiled code $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST_JAR) $(call MakeDir, $(LINK_OPT_DIR)) $(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@)) $(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $(JLI_TRACE_FILE))) $(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.raw \ $(CLASSLIST_FILE_VM_OPTS) \ + -Xint \ -Xlog:aot=off \ -Xlog:cds=off \ -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \ @@ -90,6 +93,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST -XX:SharedClassListFile=$@.interim -XX:SharedArchiveFile=$@.jsa \ -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \ $(CLASSLIST_FILE_VM_OPTS) \ + -Xint \ --module-path $(SUPPORT_OUTPUTDIR)/classlist.jar \ -Xlog:aot=off \ -Xlog:cds=off \ diff --git a/test/hotspot/jtreg/runtime/cds/DeterministicClasslist.java b/test/hotspot/jtreg/runtime/cds/DeterministicClasslist.java new file mode 100644 index 00000000000..00f12a500a4 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/DeterministicClasslist.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8378371 + * @summary The same JDK build should always generate the same classlist file (no randomness). + * @requires vm.cds & vm.flagless + * @library /test/lib ./appcds/ + * @run driver DeterministicClasslist + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.helpers.ClassFileInstaller; + + +public class DeterministicClasslist { + + public static void compareClasslists(String base, String test) throws Exception { + File baseClasslistFile = new File(base); + File testClasslistFile = new File(test); + + BufferedReader baseReader = new BufferedReader(new FileReader(baseClasslistFile)); + BufferedReader testReader = new BufferedReader(new FileReader(testClasslistFile)); + + String baseLine, testLine; + while ((baseLine = baseReader.readLine()) != null) { + testLine = testReader.readLine(); + // Skip constant pool entries + if (baseLine.contains("@cp")) { + continue; + } + if (!baseLine.equals(testLine)) { + System.out.println(baseLine + " vs " + testLine); + throw new RuntimeException("Classlists differ"); + } + } + } + + static Path findFile(String path) { + Path root = Paths.get(System.getProperty("test.root", ".")); + // Move back to java root directory + root = root.getParent().getParent().getParent(); + + Path file = root.resolve(path); + if (Files.exists(file)) { + return file; + } + + return null; + } + + public static void main (String[] args) throws Exception { + String[] classlist = { "build/tools/classlist/HelloClasslist", "build/tools/classlist/HelloClasslist$1A", "build/tools/classlist/HelloClasslist$1B" }; + String appClass = classlist[0]; + String appJar; + String classDir = System.getProperty("test.classes"); + String baseClasslist = "base.classlist"; + String testClasslist = "test.classlist"; + + Path testPath = findFile("make/jdk/src/classes/build/tools/classlist/HelloClasslist.java"); + if (testPath == null) { + throw new RuntimeException("Could not find HelloClasslist"); + } + + String source = Files.readString(testPath); + Map compiledClasses = InMemoryJavaCompiler.compile(Map.of(appClass, source)); + + for (Entry e : compiledClasses.entrySet()) { + ClassFileInstaller.writeClassToDisk(e.getKey(), e.getValue(), classDir); + } + + JarBuilder.build("classlist", classlist); + appJar = TestCommon.getTestJar("classlist.jar"); + + CDSTestUtils.dumpClassList(baseClasslist, "-cp", appJar, "-Xint", appClass); + CDSTestUtils.dumpClassList(testClasslist, "-cp", appJar, "-Xint", appClass); + + compareClasslists(baseClasslist, testClasslist); + } +} From bf28e03eeb9932ecc801b80631a43283fe525ddd Mon Sep 17 00:00:00 2001 From: Matias Saavedra Silva Date: Tue, 10 Mar 2026 20:52:14 +0000 Subject: [PATCH 156/170] 8374830: Improve Hotspot crash message in CDSTestUtils Reviewed-by: dholmes, coleenp --- test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java | 6 +++--- test/lib/jdk/test/lib/cds/CDSTestUtils.java | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java b/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java index 4e40ae3645e..8241b0f9a2e 100644 --- a/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java +++ b/test/hotspot/jtreg/runtime/cds/TestCDSVMCrash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,8 +61,8 @@ public class TestCDSVMCrash { CDSTestUtils.executeAndLog(pb, "cds_vm_crash"); throw new Error("Expected VM to crash"); } catch(RuntimeException e) { - if (!e.getMessage().equals("Hotspot crashed")) { - throw new Error("Expected message: Hotspot crashed"); + if (!e.getMessage().contains("A fatal error has been detected")) { + throw new Error("Expected message: A fatal error has been detected"); } } System.out.println("PASSED"); diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java index 13ac2e4e97a..1c51a693907 100644 --- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java +++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -696,11 +696,16 @@ public class CDSTestUtils { System.out.println("[STDOUT]\n" + output.getStdout()); if (output.getExitValue() != 0 && output.getStdout().contains("A fatal error has been detected")) { - throw new RuntimeException("Hotspot crashed"); + throw new RuntimeException(getCrashMessage(output.getStdout())); } return output; } + static String getCrashMessage(String stdOut) { + int start = stdOut.indexOf("# A fatal error has been detected by the Java Runtime Environment:"); + int end = stdOut.indexOf(".log", start) + 4; + return stdOut.substring(start, end); + } private static void writeFile(File file, String content) throws Exception { FileOutputStream fos = new FileOutputStream(file); From e760171da8825c315869e16edc01c4e450aebb0a Mon Sep 17 00:00:00 2001 From: Matias Saavedra Silva Date: Tue, 10 Mar 2026 20:57:49 +0000 Subject: [PATCH 157/170] 8376521: Verifier: disallow acmp & ifnull on 'uninitialized' types 8375483: Should set flagThisUninit whenever uninitializedThis is on the stack Reviewed-by: liach, coleenp --- src/hotspot/share/classfile/verifier.cpp | 4 +- .../classfile/impl/verifier/VerifierImpl.java | 8 +-- .../share/native/libverify/check_code.c | 5 +- .../runtime/verifier/UninitThisAcmp.jasm | 43 +++++++++++ .../runtime/verifier/UninitThisAcmpOld.jasm | 41 +++++++++++ .../runtime/verifier/UninitThisIfNull.jasm | 42 +++++++++++ .../runtime/verifier/UninitThisIfNullOld.jasm | 40 +++++++++++ .../runtime/verifier/UninitializedAcmp.jasm | 44 ++++++++++++ .../verifier/UninitializedAcmpOld.jasm | 41 +++++++++++ .../runtime/verifier/UninitializedIfNull.jasm | 42 +++++++++++ .../verifier/UninitializedIfNullOld.jasm | 39 ++++++++++ .../UninitializedThisVerificationTest.java | 58 +++++++++++++++ test/jdk/jdk/classfile/VerifierSelfTest.java | 72 ++++++++++++++++++- 13 files changed, 468 insertions(+), 11 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitThisAcmp.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitThisAcmpOld.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitThisIfNull.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitThisIfNullOld.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitializedAcmp.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitializedAcmpOld.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitializedIfNull.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitializedIfNullOld.jasm create mode 100644 test/hotspot/jtreg/runtime/verifier/UninitializedThisVerificationTest.java diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 76d09161fdd..48be24c20dc 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -1607,12 +1607,12 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { case Bytecodes::_if_acmpeq : case Bytecodes::_if_acmpne : current_frame.pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); + object_type(), CHECK_VERIFY(this)); // fall through case Bytecodes::_ifnull : case Bytecodes::_ifnonnull : current_frame.pop_stack( - VerificationType::reference_check(), CHECK_VERIFY(this)); + object_type(), CHECK_VERIFY(this)); stackmap_table.check_jump_target (¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); no_control_flow = false; break; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java index 07406b2ee7f..adc595813ee 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/verifier/VerifierImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1047,13 +1047,11 @@ public final class VerifierImpl { no_control_flow = false; break; case IF_ACMPEQ : case IF_ACMPNE : - current_frame.pop_stack( - VerificationType.reference_check); + current_frame.pop_stack(object_type()); // fall through case IFNULL : case IFNONNULL : - current_frame.pop_stack( - VerificationType.reference_check); + current_frame.pop_stack(object_type()); target = bcs.dest(); stackmap_table.check_jump_target (current_frame, target); diff --git a/src/java.base/share/native/libverify/check_code.c b/src/java.base/share/native/libverify/check_code.c index 5a8f50cd0a0..4830fedb97b 100644 --- a/src/java.base/share/native/libverify/check_code.c +++ b/src/java.base/share/native/libverify/check_code.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2162,8 +2162,7 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac break; if ( (GET_ITEM_TYPE(top_type) == ITEM_NewObject || (GET_ITEM_TYPE(top_type) == ITEM_InitObject)) - && ((opcode == JVM_OPC_astore) || (opcode == JVM_OPC_aload) - || (opcode == JVM_OPC_ifnull) || (opcode == JVM_OPC_ifnonnull))) + && ((opcode == JVM_OPC_astore) || (opcode == JVM_OPC_aload))) break; /* The 2nd edition VM of the specification allows field * initializations before the superclass initializer, diff --git a/test/hotspot/jtreg/runtime/verifier/UninitThisAcmp.jasm b/test/hotspot/jtreg/runtime/verifier/UninitThisAcmp.jasm new file mode 100644 index 00000000000..c1729a78653 --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitThisAcmp.jasm @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitThisAcmp version 69:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + aload_1; + if_acmpne L14; + nop; + L14: stack_frame_type append; + locals_map class java/lang/Object; + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisAcmp diff --git a/test/hotspot/jtreg/runtime/verifier/UninitThisAcmpOld.jasm b/test/hotspot/jtreg/runtime/verifier/UninitThisAcmpOld.jasm new file mode 100644 index 00000000000..3bcc1e09b67 --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitThisAcmpOld.jasm @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitThisAcmpOld version 49:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + aload_1; + if_acmpne L14; + nop; + L14: aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisAcmpOld diff --git a/test/hotspot/jtreg/runtime/verifier/UninitThisIfNull.jasm b/test/hotspot/jtreg/runtime/verifier/UninitThisIfNull.jasm new file mode 100644 index 00000000000..57a82a9f1e4 --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitThisIfNull.jasm @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitThisIfNull version 69:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + ifnonnull L14; + nop; + L14: stack_frame_type append; + locals_map class java/lang/Object; + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisIfNull diff --git a/test/hotspot/jtreg/runtime/verifier/UninitThisIfNullOld.jasm b/test/hotspot/jtreg/runtime/verifier/UninitThisIfNullOld.jasm new file mode 100644 index 00000000000..fbe96c2eef0 --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitThisIfNullOld.jasm @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitThisIfNullOld version 49:0 +{ + public Method "":"()V" + stack 2 locals 2 + { + new class java/lang/Object; + dup; + invokespecial Method java/lang/Object."":"()V"; + astore_1; + aload_0; + ifnonnull L14; + nop; + L14: aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitThisIfNullOld diff --git a/test/hotspot/jtreg/runtime/verifier/UninitializedAcmp.jasm b/test/hotspot/jtreg/runtime/verifier/UninitializedAcmp.jasm new file mode 100644 index 00000000000..b8ce17cb16b --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitializedAcmp.jasm @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitializedAcmp version 69:0 +{ + Method "":"()V" + stack 5 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + aload_0; + L1: new class java/lang/Object; + dup; + dup; + dup; + if_acmpne L18; + nop; + L18: stack_frame_type full; + locals_map class UninitializedAcmp; + stack_map class UninitializedAcmp, at L1, at L1; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedAcmp diff --git a/test/hotspot/jtreg/runtime/verifier/UninitializedAcmpOld.jasm b/test/hotspot/jtreg/runtime/verifier/UninitializedAcmpOld.jasm new file mode 100644 index 00000000000..d16cc5c6779 --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitializedAcmpOld.jasm @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitializedAcmpOld version 49:0 +{ + Method "":"()V" + stack 5 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + aload_0; + L1: new class java/lang/Object; + dup; + dup; + dup; + if_acmpne L18; + nop; + L18: invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedAcmpOld diff --git a/test/hotspot/jtreg/runtime/verifier/UninitializedIfNull.jasm b/test/hotspot/jtreg/runtime/verifier/UninitializedIfNull.jasm new file mode 100644 index 00000000000..4e7251f073d --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitializedIfNull.jasm @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitializedIfNull version 69:0 +{ + Method "":"()V" + stack 3 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + L1: new class java/lang/Object; + dup; + dup; + ifnonnull L18; + nop; + L18: stack_frame_type full; + locals_map class UninitializedIfNull; + stack_map at L1, at L1; + invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedIfNull diff --git a/test/hotspot/jtreg/runtime/verifier/UninitializedIfNullOld.jasm b/test/hotspot/jtreg/runtime/verifier/UninitializedIfNullOld.jasm new file mode 100644 index 00000000000..5bffba887a8 --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitializedIfNullOld.jasm @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +class UninitializedIfNullOld version 49:0 +{ + Method "":"()V" + stack 3 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + L1: new class java/lang/Object; + dup; + dup; + ifnonnull L18; + nop; + L18: invokespecial Method java/lang/Object."":"()V"; + return; + } +} // end Class UninitializedIfNullOld diff --git a/test/hotspot/jtreg/runtime/verifier/UninitializedThisVerificationTest.java b/test/hotspot/jtreg/runtime/verifier/UninitializedThisVerificationTest.java new file mode 100644 index 00000000000..075e9f2058e --- /dev/null +++ b/test/hotspot/jtreg/runtime/verifier/UninitializedThisVerificationTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8366743 + * @summary Test spec rules for uninitialized + * @compile UninitThisAcmp.jasm UninitThisIfNull.jasm + * UninitializedIfNull.jasm UninitializedAcmp.jasm + * UninitThisAcmpOld.jasm UninitThisIfNullOld.jasm + * UninitializedAcmpOld.jasm UninitializedIfNullOld.jasm + * @run main/othervm -Xlog:verification UninitializedThisVerificationTest + */ + +public class UninitializedThisVerificationTest { + + public static void main(String[] args) throws Exception { + String[] testNames = { "UninitThisAcmp", "UninitThisIfNull", + "UninitializedAcmp", "UninitializedIfNull", + "UninitThisAcmpOld", "UninitThisIfNullOld", + "UninitializedAcmpOld", "UninitializedIfNullOld" }; + int fails = 0; + for (String test : testNames) { + System.out.println("Testing " + test); + try { + Class c = Class.forName(test); + System.out.println("Failed"); + fails++; + } catch (java.lang.VerifyError e) { + System.out.println("Passed"); + } + } + + if (fails > 0) { + throw new RuntimeException("Failed: Expected VerifyError in " + fails + " tests"); + } + } +} diff --git a/test/jdk/jdk/classfile/VerifierSelfTest.java b/test/jdk/jdk/classfile/VerifierSelfTest.java index 7d1dae6f519..12458b1586e 100644 --- a/test/jdk/jdk/classfile/VerifierSelfTest.java +++ b/test/jdk/jdk/classfile/VerifierSelfTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,12 +37,14 @@ import static java.lang.constant.ConstantDescs.*; import java.lang.constant.MethodTypeDesc; import java.lang.invoke.MethodHandleInfo; +import java.lang.invoke.MethodHandles; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -59,6 +61,9 @@ import jdk.internal.classfile.impl.BufWriterImpl; import jdk.internal.classfile.impl.DirectClassBuilder; import jdk.internal.classfile.impl.UnboundAttribute; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.*; @@ -418,6 +423,71 @@ class VerifierSelfTest { return lst; } + enum ComparisonInstruction { + IF_ACMPEQ(Opcode.IF_ACMPEQ, 2), + IF_ACMPNE(Opcode.IF_ACMPNE, 2), + IFNONNULL(Opcode.IFNONNULL, 1), + IFNULL(Opcode.IFNULL, 1); + final Opcode opcode; + final int argCount; + ComparisonInstruction(Opcode opcode, int argCount) { + this.opcode = opcode; + this.argCount = argCount; + } + } + + enum UninitializeKind { + UNINITIALIZED, UNINITIALIZED_THIS + } + + @ParameterizedTest + @MethodSource("uninitializedInBytecodeClasses") + public void testUninitializedInComparisons(ComparisonInstruction inst, UninitializeKind kind) throws Throwable { + var bytes = ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).build(ClassDesc.of("Test"), clb -> clb + .withMethodBody(INIT_NAME, MTD_void, 0, cob -> { + StackMapFrameInfo.VerificationTypeInfo uninitializeInfo; + if (kind == UninitializeKind.UNINITIALIZED) { + uninitializeInfo = StackMapFrameInfo.UninitializedVerificationTypeInfo.of(cob.newBoundLabel()); + cob.new_(CD_Object); + } else { + uninitializeInfo = StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS; + cob.aload(0); + } + + // Stack: uninitializeInfo + for (int i = 0; i < inst.argCount; i++) { + cob.dup(); + } + var dest = cob.newLabel(); + cob.branch(inst.opcode, dest) + .nop() + .labelBinding(dest) + .with(StackMapTableAttribute.of(List.of(StackMapFrameInfo.of(dest, + List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.UNINITIALIZED_THIS), + List.of(uninitializeInfo))))) + .invokespecial(CD_Object, INIT_NAME, MTD_void); + if (kind == UninitializeKind.UNINITIALIZED) { + // still need to call super constructor + cob.aload(0) + .invokespecial(CD_Object, INIT_NAME, MTD_void); + } + cob.return_(); + })); + var errors = ClassFile.of().verify(bytes); + assertNotEquals(List.of(), errors, () -> errors + " : " + ClassFile.of().parse(bytes).toDebugString()); + var lookup = MethodHandles.lookup(); + assertThrows(VerifyError.class, () -> lookup.defineHiddenClass(bytes, true)); // force JVM verification + } + + public static Stream uninitializedInBytecodeClasses() { + return Arrays.stream(ComparisonInstruction.values()) + .mapMulti((inst, sink) -> { + for (var kind : UninitializeKind.values()) { + sink.accept(Arguments.of(inst, kind)); + } + }); + } + @Test // JDK-8350029 void testInvokeSpecialInterfacePatch() { var runClass = ClassDesc.of("Run"); From a4daabbbfa3184b0dcce1db73502f69f601978f0 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Tue, 10 Mar 2026 22:13:37 +0000 Subject: [PATCH 158/170] 8237220: [macOS] AWT text test CorrectTextComponentSelectionTest.html sometimes fails Reviewed-by: aivanov, prr, dmarkov --- test/jdk/ProblemList.txt | 1 - .../CorrectTextComponentSelectionTest.java | 39 ++++++------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index de1a0a49d1e..38ffe2ae963 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -758,7 +758,6 @@ java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all, java/awt/FileDialog/DoubleActionESC.java 8356981 linux-all java/awt/print/PageFormat/Orient.java 8016055 macosx-all java/awt/TextArea/TextAreaCursorTest/HoveringAndDraggingTest.java 8024986 macosx-all,linux-all -java/awt/TextComponent/CorrectTextComponentSelectionTest.java 8237220 macosx-all java/awt/TextComponent/SelectionAndCaretColor.java 7017622 linux-all java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter.java 8254841 macosx-all java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all diff --git a/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java b/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java index 9d3e6d85637..b2352dc04ff 100644 --- a/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java +++ b/test/jdk/java/awt/TextComponent/CorrectTextComponentSelectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,9 @@ /* * @test + * @key headful * @bug 5100806 * @summary TextArea.select(0,0) does not de-select the selected text properly - * @key headful * @run main CorrectTextComponentSelectionTest */ @@ -38,7 +38,6 @@ import java.awt.Robot; import java.awt.TextArea; import java.awt.TextComponent; import java.awt.TextField; -import java.lang.reflect.InvocationTargetException; public class CorrectTextComponentSelectionTest { static TextField tf = new TextField("TextField"); @@ -46,14 +45,11 @@ public class CorrectTextComponentSelectionTest { static Robot r; static Frame frame; static volatile Color color_center; - static volatile Point loc; public static void main(String[] args) throws Exception { try { r = new Robot(); - EventQueue.invokeAndWait(() -> { - initialize(); - }); + EventQueue.invokeAndWait(() -> initialize()); r.waitForIdle(); r.delay(1000); @@ -75,24 +71,13 @@ public class CorrectTextComponentSelectionTest { // We should place to the text components the long strings in order to // cover the components by the selection completely - String sf = ""; - for (int i = 0; i < 50; i++) { - sf = sf + " "; - } - tf.setText(sf); + tf.setText(" ".repeat(50)); // We check the color of the text component in order to find out the // bug reproducible situation tf.setForeground(Color.WHITE); tf.setBackground(Color.WHITE); - String sa = ""; - for (int i = 0; i < 50; i++) { - for (int j = 0; j < 50; j++) { - sa = sa + " "; - } - sa = sa + "\n"; - } - ta.setText(sa); + ta.setText((" ".repeat(50) + "\n").repeat(50)); ta.setForeground(Color.WHITE); ta.setBackground(Color.WHITE); @@ -111,26 +96,24 @@ public class CorrectTextComponentSelectionTest { r.waitForIdle(); r.delay(100); + EventQueue.invokeAndWait(() -> { tc.requestFocus(); tc.selectAll(); tc.select(0, 0); }); - r.waitForIdle(); - r.delay(100); - EventQueue.invokeAndWait(() -> { - loc = tc.getLocationOnScreen(); - }); r.waitForIdle(); r.delay(100); EventQueue.invokeAndWait(() -> { - color_center = r.getPixelColor(loc.x + tc.getWidth() / 2, loc.y + tc.getHeight() / 2); + Point p = tc.getLocationOnScreen(); + p.translate(tc.getWidth() / 2, tc.getHeight() / 2); + color_center = r.getPixelColor(p.x, p.y); }); - System.out.println("Color of the text component (CENTER) =" + color_center); - System.out.println("White color=" + Color.WHITE); + System.out.println("Color of the text component (CENTER) = " + color_center); + System.out.println("White color = " + Color.WHITE); if (color_center.getRGB() != Color.WHITE.getRGB()) { throw new RuntimeException("Test Failed"); From 9d04c8a8af808afc8fc3162555030ad7faed5beb Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 10 Mar 2026 23:46:53 +0000 Subject: [PATCH 159/170] 8379432: jpackage: Make default equals() in jdk.jpackage.test.CannedFormattedString class work as expected Reviewed-by: almatvee --- .../jdk/jpackage/test/CannedArgumentTest.java | 39 ++++++++ .../test/CannedFormattedStringTest.java | 99 +++++++++++++++++++ .../test/JPackageStringBundleTest.java | 19 ++++ .../jdk/jpackage/test/CannedArgument.java | 30 ++++++ .../jpackage/test/CannedFormattedString.java | 60 +++++------ .../jdk/jpackage/test/JPackageCommand.java | 4 +- .../jpackage/test/JPackageStringBundle.java | 11 ++- test/jdk/tools/jpackage/share/ErrorTest.java | 2 +- 8 files changed, 218 insertions(+), 46 deletions(-) create mode 100644 test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedArgumentTest.java create mode 100644 test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedFormattedStringTest.java diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedArgumentTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedArgumentTest.java new file mode 100644 index 00000000000..8653e9c7508 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedArgumentTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.nio.file.Path; +import jdk.jpackage.test.CannedFormattedStringTest.Formatter; +import org.junit.jupiter.api.Test; + +class CannedArgumentTest { + + @Test + void test_cannedAbsolutePath() { + var a = Formatter.MESSAGE_FORMAT.create("Current directory: {0}", CannedArgument.cannedAbsolutePath("foo")); + assertEquals("Current directory: " + Path.of("foo").toAbsolutePath(), a.getValue()); + assertEquals("Current directory: {0}+[AbsolutePath(foo)]", a.toString()); + } +} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedFormattedStringTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedFormattedStringTest.java new file mode 100644 index 00000000000..2e4ad9ab754 --- /dev/null +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/CannedFormattedStringTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jpackage.test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; + +import java.text.MessageFormat; +import java.util.List; +import java.util.function.BiFunction; +import org.junit.jupiter.api.Test; + +class CannedFormattedStringTest { + + @Test + void test_getValue() { + var a = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}", "Duke"); + assertEquals("Hello Duke! Bye Duke", a.getValue()); + assertEquals("Hello {0}! Bye {0}+[Duke]", a.toString()); + + var b = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}"); + assertEquals("Hello {0}! Bye {0}", b.getValue()); + assertEquals("Hello {0}! Bye {0}", b.toString()); + } + + @Test + void test_equals() { + var a = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}", "Duke"); + var b = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}", "Duke"); + + assertEquals(a, b); + + a = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}", "Duke"); + b = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}", "Java"); + + assertNotEquals(a, b); + } + + @Test + void test_addPrefix() { + var a = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}", "Duke"); + var b = a.addPrefix("{0} and {0}").addPrefix("They say: {0}"); + var str = "Hello Duke! Bye Duke"; + assertEquals(str, a.getValue()); + assertEquals("They say: " + str + " and " + str, b.getValue()); + assertEquals("They say: {0}+[{0} and {0}, Hello {0}! Bye {0}, Duke]", b.toString()); + + var c = a.addPrefix("{0} and {0}").addPrefix("They say: {0}"); + assertEquals(c, b); + assertNotSame(b, c); + } + + @Test + void test_mapArgs() { + var a = Formatter.MESSAGE_FORMAT.create("Hello {0}! Bye {0}", "Duke"); + var b = a.mapArgs(arg -> { + assertEquals("Duke", arg); + return "Java"; + }); + + assertEquals("Hello Duke! Bye Duke", a.getValue()); + assertEquals("Hello Java! Bye Java", b.getValue()); + } + + enum Formatter implements BiFunction { + MESSAGE_FORMAT { + @Override + public String apply(String format, Object[] formatArgs) { + return MessageFormat.format(format, formatArgs); + } + }, + ; + + CannedFormattedString create(String format, Object ... formatArgs) { + return new CannedFormattedString(this, format, List.of(formatArgs)); + } + } +} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java index bf1eb2bdaec..0512d03b76a 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JPackageStringBundleTest.java @@ -24,6 +24,7 @@ package jdk.jpackage.test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -46,6 +47,24 @@ class JPackageStringBundleTest { assertFalse(JPackageStringBundle.MAIN.cannedFormattedString("error.version-string-empty").getValue().isBlank()); } + @Test + void test_cannedFormattedString_equals() { + var a = JPackageStringBundle.MAIN.cannedFormattedString("error.version-string-empty"); + var b = JPackageStringBundle.MAIN.cannedFormattedString("error.version-string-empty"); + + assertEquals(a, b); + + a = JPackageStringBundle.MAIN.cannedFormattedString("message.error-header", "foo"); + b = JPackageStringBundle.MAIN.cannedFormattedString("message.error-header", "foo"); + + assertEquals(a, b); + + a = JPackageStringBundle.MAIN.cannedFormattedString("message.error-header", "foo"); + b = JPackageStringBundle.MAIN.cannedFormattedString("message.error-header", "bar"); + + assertNotEquals(a, b); + } + @Test void test_cannedFormattedStringAsPattern() { var pred = JPackageStringBundle.MAIN.cannedFormattedStringAsPattern("error.version-string-empty", UNREACHABLE_FORMAT_ARG_MAPPER).asMatchPredicate(); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedArgument.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedArgument.java index b50d12ac4ec..346b172fa35 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedArgument.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedArgument.java @@ -22,7 +22,37 @@ */ package jdk.jpackage.test; +import java.nio.file.Path; +import java.util.Objects; +import java.util.function.Supplier; + @FunctionalInterface public interface CannedArgument { + public String getValue(); + + public static CannedArgument create(Supplier supplier, String label) { + Objects.requireNonNull(supplier); + Objects.requireNonNull(label); + return new CannedArgument() { + + @Override + public String getValue() { + return supplier.get().toString(); + } + + @Override + public String toString( ) { + return label; + } + }; + } + + public static Object cannedAbsolutePath(Path v) { + return create(v::toAbsolutePath, String.format("AbsolutePath(%s)", v)); + } + + public static Object cannedAbsolutePath(String v) { + return cannedAbsolutePath(Path.of(v)); + } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedFormattedString.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedFormattedString.java index 09f867da786..d5248ee2b17 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedFormattedString.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/CannedFormattedString.java @@ -22,55 +22,29 @@ */ package jdk.jpackage.test; -import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.function.BiFunction; -import java.util.function.Supplier; import java.util.function.UnaryOperator; import java.util.stream.Stream; -public record CannedFormattedString(BiFunction formatter, String key, Object[] args) implements CannedArgument { - - public static CannedArgument cannedArgument(Supplier supplier, String label) { - Objects.requireNonNull(supplier); - Objects.requireNonNull(label); - return new CannedArgument() { - - @Override - public String getValue() { - return supplier.get().toString(); - } - - @Override - public String toString( ) { - return label; - } - }; - } - - public static Object cannedAbsolutePath(Path v) { - return cannedArgument(() -> v.toAbsolutePath(), String.format("AbsolutePath(%s)", v)); - } - - public static Object cannedAbsolutePath(String v) { - return cannedAbsolutePath(Path.of(v)); - } +public record CannedFormattedString(BiFunction formatter, String key, List args) implements CannedArgument { public CannedFormattedString mapArgs(UnaryOperator mapper) { - return new CannedFormattedString(formatter, key, Stream.of(args).map(mapper).toArray()); + return new CannedFormattedString(formatter, key, args.stream().map(mapper).toList()); } public CannedFormattedString { Objects.requireNonNull(formatter); Objects.requireNonNull(key); Objects.requireNonNull(args); - List.of(args).forEach(Objects::requireNonNull); + args.forEach(Objects::requireNonNull); } + @Override public String getValue() { - return formatter.apply(key, Stream.of(args).map(arg -> { + return formatter.apply(key, args.stream().map(arg -> { if (arg instanceof CannedArgument cannedArg) { return cannedArg.getValue(); } else { @@ -80,19 +54,29 @@ public record CannedFormattedString(BiFunction formatt } public CannedFormattedString addPrefix(String prefixKey) { - Objects.requireNonNull(prefixKey); - return new CannedFormattedString((theKey, theArgs) -> { - var str = formatter.apply((String)theArgs[0], Arrays.copyOfRange(theArgs, 1, theArgs.length)); - return formatter.apply(theKey, new Object[] {str}); - }, prefixKey, Stream.concat(Stream.of(key), Stream.of(args)).toArray()); + return new CannedFormattedString( + new AddPrefixFormatter(formatter), prefixKey, Stream.concat(Stream.of(key), args.stream()).toList()); } @Override public String toString() { - if (args.length == 0) { + if (args.isEmpty()) { return String.format("%s", key); } else { - return String.format("%s+%s", key, List.of(args)); + return String.format("%s+%s", key, args); + } + } + + private record AddPrefixFormatter(BiFunction formatter) implements BiFunction { + + AddPrefixFormatter { + Objects.requireNonNull(formatter); + } + + @Override + public String apply(String format, Object[] formatArgs) { + var str = formatter.apply((String)formatArgs[0], Arrays.copyOfRange(formatArgs, 1, formatArgs.length)); + return formatter.apply(format, new Object[] {str}); } } } 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 f68ac90d284..67c0ba41e3f 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -966,13 +966,13 @@ public class JPackageCommand extends CommandArguments { } public String getValue(CannedFormattedString str) { - return new CannedFormattedString(str.formatter(), str.key(), Stream.of(str.args()).map(arg -> { + return new CannedFormattedString(str.formatter(), str.key(), str.args().stream().map(arg -> { if (arg instanceof CannedArgument cannedArg) { return cannedArg.value(this); } else { return arg; } - }).toArray()).getValue(); + }).toList()).getValue(); } public JPackageCommand validateOut(CannedFormattedString... strings) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java index cd8ffd853b7..dcf994a0e93 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java @@ -31,6 +31,7 @@ import java.text.MessageFormat; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.regex.Pattern; @@ -48,6 +49,9 @@ public enum JPackageStringBundle { } catch (ClassNotFoundException|NoSuchMethodException ex) { throw toUnchecked(ex); } + formatter = (String key, Object[] args) -> { + return new FormattedMessage(key, args).value(); + }; } /** @@ -61,12 +65,8 @@ public enum JPackageStringBundle { } } - private String getFormattedString(String key, Object[] args) { - return new FormattedMessage(key, args).value(); - } - public CannedFormattedString cannedFormattedString(String key, Object ... args) { - return new CannedFormattedString(this::getFormattedString, key, args); + return new CannedFormattedString(formatter, key, List.of(args)); } public Pattern cannedFormattedStringAsPattern(String key, Function formatArgMapper, Object ... args) { @@ -153,4 +153,5 @@ public enum JPackageStringBundle { private final Class i18nClass; private final Method i18nClass_getString; + private final BiFunction formatter; } diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index db87263884b..2797115b202 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -713,7 +713,7 @@ public final class ErrorTest { private static void testMacSignWithoutIdentityWithNewTKitState(TestSpec spec) { final Token keychainToken = spec.expectedMessages().stream().flatMap(cannedStr -> { - return Stream.of(cannedStr.args()).filter(Token.class::isInstance).map(Token.class::cast).filter(token -> { + return cannedStr.args().stream().filter(Token.class::isInstance).map(Token.class::cast).filter(token -> { switch (token) { case EMPTY_KEYCHAIN, KEYCHAIN_WITH_APP_IMAGE_CERT, KEYCHAIN_WITH_PKG_CERT -> { return true; From 8b8bb43396fe12992cd3ae1bfdff7c9c317bddbf Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Wed, 11 Mar 2026 00:22:01 +0000 Subject: [PATCH 160/170] 8379256: Update GIFlib to 6.1.1 Reviewed-by: prr, kizune --- src/java.desktop/share/legal/giflib.md | 10 +- .../native/libsplashscreen/giflib/COPYING | 2 +- .../native/libsplashscreen/giflib/dgif_lib.c | 1875 +++++++++-------- .../native/libsplashscreen/giflib/gif_err.c | 156 +- .../native/libsplashscreen/giflib/gif_hash.h | 7 +- .../native/libsplashscreen/giflib/gif_lib.h | 102 +- .../libsplashscreen/giflib/gif_lib_private.h | 48 +- .../native/libsplashscreen/giflib/gifalloc.c | 590 +++--- .../giflib/openbsd-reallocarray.c | 105 +- 9 files changed, 1461 insertions(+), 1434 deletions(-) diff --git a/src/java.desktop/share/legal/giflib.md b/src/java.desktop/share/legal/giflib.md index 5697dc7ca9a..ba2dbb00535 100644 --- a/src/java.desktop/share/legal/giflib.md +++ b/src/java.desktop/share/legal/giflib.md @@ -1,9 +1,9 @@ -## GIFLIB v5.2.2 +## GIFLIB v6.1.1 ### GIFLIB License ``` -The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond += MIT LICENSE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,9 +25,15 @@ THE SOFTWARE. --------------------------------- The below applies to the following file(s): +giflib/dgif_lib.c +giflib/gifalloc.c +giflib/gif_err.c giflib/openbsd-reallocarray.c +Copyright (C) 1989 Gershon Elber Copyright (C) 2008 Otto Moerbeek +Copyright (C) Eric S. Raymond + SPDX-License-Identifier: MIT diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/COPYING b/src/java.desktop/share/native/libsplashscreen/giflib/COPYING index b9c0b501260..92774a3b036 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/COPYING +++ b/src/java.desktop/share/native/libsplashscreen/giflib/COPYING @@ -1,4 +1,4 @@ -The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond += MIT LICENSE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c b/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c index 0b2860b4b50..2fa005ed20d 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c @@ -30,9 +30,9 @@ The functions here and in egif_lib.c are partitioned carefully so that if you only require one of read and write capability, only one of these two modules will be linked. Preserve this property! -SPDX-License-Identifier: MIT - *****************************************************************************/ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: Copyright (C) Eric S. Raymond #include #include @@ -55,11 +55,11 @@ SPDX-License-Identifier: MIT /* avoid extra function call in case we use fread (TVT) */ static int InternalRead(GifFileType *gif, GifByteType *buf, int len) { - // fprintf(stderr, "### Read: %d\n", len); - return (((GifFilePrivateType *)gif->Private)->Read - ? ((GifFilePrivateType *)gif->Private)->Read(gif, buf, len) - : fread(buf, 1, len, - ((GifFilePrivateType *)gif->Private)->File)); + // fprintf(stderr, "### Read: %d\n", len); + return (((GifFilePrivateType *)gif->Private)->Read + ? ((GifFilePrivateType *)gif->Private)->Read(gif, buf, len) + : fread(buf, 1, len, + ((GifFilePrivateType *)gif->Private)->File)); } static int DGifGetWord(GifFileType *GifFile, GifWord *Word); @@ -78,18 +78,18 @@ static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, info record. ******************************************************************************/ GifFileType *DGifOpenFileName(const char *FileName, int *Error) { - int FileHandle; - GifFileType *GifFile; + int FileHandle; + GifFileType *GifFile; - if ((FileHandle = open(FileName, O_RDONLY)) == -1) { - if (Error != NULL) { - *Error = D_GIF_ERR_OPEN_FAILED; + if ((FileHandle = open(FileName, O_RDONLY)) == -1) { + if (Error != NULL) { + *Error = D_GIF_ERR_OPEN_FAILED; + } + return NULL; } - return NULL; - } - GifFile = DGifOpenFileHandle(FileHandle, Error); - return GifFile; + GifFile = DGifOpenFileHandle(FileHandle, Error); + return GifFile; } /****************************************************************************** @@ -98,171 +98,171 @@ GifFileType *DGifOpenFileName(const char *FileName, int *Error) { info record. ******************************************************************************/ GifFileType *DGifOpenFileHandle(int FileHandle, int *Error) { - char Buf[GIF_STAMP_LEN + 1]; - GifFileType *GifFile; - GifFilePrivateType *Private; - FILE *f; + char Buf[GIF_STAMP_LEN + 1]; + GifFileType *GifFile; + GifFilePrivateType *Private; + FILE *f; - GifFile = (GifFileType *)malloc(sizeof(GifFileType)); - if (GifFile == NULL) { - if (Error != NULL) { - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile = (GifFileType *)malloc(sizeof(GifFileType)); + if (GifFile == NULL) { + if (Error != NULL) { + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } + (void)close(FileHandle); + return NULL; } - (void)close(FileHandle); - return NULL; - } - /*@i1@*/ memset(GifFile, '\0', sizeof(GifFileType)); + /*@i1@*/ memset(GifFile, '\0', sizeof(GifFileType)); - /* Belt and suspenders, in case the null pointer isn't zero */ - GifFile->SavedImages = NULL; - GifFile->SColorMap = NULL; + /* Belt and suspenders, in case the null pointer isn't zero */ + GifFile->SavedImages = NULL; + GifFile->SColorMap = NULL; - Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType)); - if (Private == NULL) { - if (Error != NULL) { - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType)); + if (Private == NULL) { + if (Error != NULL) { + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } + (void)close(FileHandle); + free((char *)GifFile); + return NULL; } - (void)close(FileHandle); - free((char *)GifFile); - return NULL; - } - /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType)); + /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType)); #ifdef _WIN32 - _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ + _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ #endif /* _WIN32 */ - f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ + f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ - /*@-mustfreeonly@*/ - GifFile->Private = (void *)Private; - Private->FileHandle = FileHandle; - Private->File = f; - Private->FileState = FILE_STATE_READ; - Private->Read = NULL; /* don't use alternate input method (TVT) */ - GifFile->UserData = NULL; /* TVT */ - /*@=mustfreeonly@*/ + /*@-mustfreeonly@*/ + GifFile->Private = (void *)Private; + Private->FileHandle = FileHandle; + Private->File = f; + Private->FileState = FILE_STATE_READ; + Private->Read = NULL; /* don't use alternate input method (TVT) */ + GifFile->UserData = NULL; /* TVT */ + /*@=mustfreeonly@*/ - /* Let's see if this is a GIF file: */ - /* coverity[check_return] */ - if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != - GIF_STAMP_LEN) { - if (Error != NULL) { - *Error = D_GIF_ERR_READ_FAILED; + /* Let's see if this is a GIF file: */ + /* coverity[check_return] */ + if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != + GIF_STAMP_LEN) { + if (Error != NULL) { + *Error = D_GIF_ERR_READ_FAILED; + } + (void)fclose(f); + free((char *)Private); + free((char *)GifFile); + return NULL; } - (void)fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } - /* Check for GIF prefix at start of file */ - Buf[GIF_STAMP_LEN] = 0; - if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - if (Error != NULL) { - *Error = D_GIF_ERR_NOT_GIF_FILE; + /* Check for GIF prefix at start of file */ + Buf[GIF_STAMP_LEN] = 0; + if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { + if (Error != NULL) { + *Error = D_GIF_ERR_NOT_GIF_FILE; + } + (void)fclose(f); + free((char *)Private); + free((char *)GifFile); + return NULL; } - (void)fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } - if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - (void)fclose(f); - free((char *)Private); - free((char *)GifFile); - return NULL; - } + if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { + (void)fclose(f); + free((char *)Private); + free((char *)GifFile); + return NULL; + } - GifFile->Error = 0; + GifFile->Error = 0; - /* What version of GIF? */ - Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9'); + /* What version of GIF? */ + Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9'); - return GifFile; + return GifFile; } /****************************************************************************** GifFileType constructor with user supplied input function (TVT) ******************************************************************************/ GifFileType *DGifOpen(void *userData, InputFunc readFunc, int *Error) { - char Buf[GIF_STAMP_LEN + 1]; - GifFileType *GifFile; - GifFilePrivateType *Private; + char Buf[GIF_STAMP_LEN + 1]; + GifFileType *GifFile; + GifFilePrivateType *Private; - GifFile = (GifFileType *)malloc(sizeof(GifFileType)); - if (GifFile == NULL) { - if (Error != NULL) { - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile = (GifFileType *)malloc(sizeof(GifFileType)); + if (GifFile == NULL) { + if (Error != NULL) { + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } + return NULL; } - return NULL; - } - memset(GifFile, '\0', sizeof(GifFileType)); + memset(GifFile, '\0', sizeof(GifFileType)); - /* Belt and suspenders, in case the null pointer isn't zero */ - GifFile->SavedImages = NULL; - GifFile->SColorMap = NULL; + /* Belt and suspenders, in case the null pointer isn't zero */ + GifFile->SavedImages = NULL; + GifFile->SColorMap = NULL; - Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType)); - if (!Private) { - if (Error != NULL) { - *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType)); + if (!Private) { + if (Error != NULL) { + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + } + free((char *)GifFile); + return NULL; } - free((char *)GifFile); - return NULL; - } - /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType)); + /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType)); - GifFile->Private = (void *)Private; - Private->FileHandle = 0; - Private->File = NULL; - Private->FileState = FILE_STATE_READ; + GifFile->Private = (void *)Private; + Private->FileHandle = 0; + Private->File = NULL; + Private->FileState = FILE_STATE_READ; - Private->Read = readFunc; /* TVT */ - GifFile->UserData = userData; /* TVT */ + Private->Read = readFunc; /* TVT */ + GifFile->UserData = userData; /* TVT */ - /* Lets see if this is a GIF file: */ - /* coverity[check_return] */ - if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != - GIF_STAMP_LEN) { - if (Error != NULL) { - *Error = D_GIF_ERR_READ_FAILED; + /* Lets see if this is a GIF file: */ + /* coverity[check_return] */ + if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != + GIF_STAMP_LEN) { + if (Error != NULL) { + *Error = D_GIF_ERR_READ_FAILED; + } + free((char *)Private); + free((char *)GifFile); + return NULL; } - free((char *)Private); - free((char *)GifFile); - return NULL; - } - /* Check for GIF prefix at start of file */ - Buf[GIF_STAMP_LEN] = '\0'; - if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { - if (Error != NULL) { - *Error = D_GIF_ERR_NOT_GIF_FILE; + /* Check for GIF prefix at start of file */ + Buf[GIF_STAMP_LEN] = '\0'; + if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { + if (Error != NULL) { + *Error = D_GIF_ERR_NOT_GIF_FILE; + } + free((char *)Private); + free((char *)GifFile); + return NULL; } - free((char *)Private); - free((char *)GifFile); - return NULL; - } - if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { - free((char *)Private); - free((char *)GifFile); - if (Error != NULL) { - *Error = D_GIF_ERR_NO_SCRN_DSCR; + if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { + free((char *)Private); + free((char *)GifFile); + if (Error != NULL) { + *Error = D_GIF_ERR_NO_SCRN_DSCR; + } + return NULL; } - return NULL; - } - GifFile->Error = 0; + GifFile->Error = 0; - /* What version of GIF? */ - Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9'); + /* What version of GIF? */ + Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9'); - return GifFile; + return GifFile; } /****************************************************************************** @@ -270,180 +270,180 @@ GifFileType *DGifOpen(void *userData, InputFunc readFunc, int *Error) { this routine is called automatically from DGif file open routines. ******************************************************************************/ int DGifGetScreenDesc(GifFileType *GifFile) { - int BitsPerPixel; - bool SortFlag; - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + int BitsPerPixel; + bool SortFlag; + GifByteType Buf[3]; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - /* Put the screen descriptor into the file: */ - if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) { - return GIF_ERROR; - } - - if (InternalRead(GifFile, Buf, 3) != 3) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - GifFreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - return GIF_ERROR; - } - GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; - SortFlag = (Buf[0] & 0x08) != 0; - BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->SBackGroundColor = Buf[1]; - GifFile->AspectByte = Buf[2]; - if (Buf[0] & 0x80) { /* Do we have global color map? */ - int i; - - GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->SColorMap == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; } - /* Get the global color map: */ - GifFile->SColorMap->SortFlag = SortFlag; - for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { - /* coverity[check_return] */ - if (InternalRead(GifFile, Buf, 3) != 3) { + /* Put the screen descriptor into the file: */ + if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || + DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) { + return GIF_ERROR; + } + + if (InternalRead(GifFile, Buf, 3) != 3) { + GifFile->Error = D_GIF_ERR_READ_FAILED; GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; - GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; - } - GifFile->SColorMap->Colors[i].Red = Buf[0]; - GifFile->SColorMap->Colors[i].Green = Buf[1]; - GifFile->SColorMap->Colors[i].Blue = Buf[2]; } - } else { - GifFile->SColorMap = NULL; - } + GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; + SortFlag = (Buf[0] & 0x08) != 0; + BitsPerPixel = (Buf[0] & 0x07) + 1; + GifFile->SBackGroundColor = Buf[1]; + GifFile->AspectByte = Buf[2]; + if (Buf[0] & 0x80) { /* Do we have global color map? */ + int i; - /* - * No check here for whether the background color is in range for the - * screen color map. Possibly there should be. - */ + GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); + if (GifFile->SColorMap == NULL) { + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; + return GIF_ERROR; + } - return GIF_OK; + /* Get the global color map: */ + GifFile->SColorMap->SortFlag = SortFlag; + for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { + /* coverity[check_return] */ + if (InternalRead(GifFile, Buf, 3) != 3) { + GifFreeMapObject(GifFile->SColorMap); + GifFile->SColorMap = NULL; + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + GifFile->SColorMap->Colors[i].Red = Buf[0]; + GifFile->SColorMap->Colors[i].Green = Buf[1]; + GifFile->SColorMap->Colors[i].Blue = Buf[2]; + } + } else { + GifFile->SColorMap = NULL; + } + + /* + * No check here for whether the background color is in range for the + * screen color map. Possibly there should be. + */ + + return GIF_OK; } const char *DGifGetGifVersion(GifFileType *GifFile) { - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (Private->gif89) { - return GIF89_STAMP; - } else { - return GIF87_STAMP; - } + if (Private->gif89) { + return GIF89_STAMP; + } else { + return GIF87_STAMP; + } } /****************************************************************************** This routine should be called before any attempt to read an image. ******************************************************************************/ int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type) { - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } - /* coverity[check_return] */ - if (InternalRead(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } + /* coverity[check_return] */ + if (InternalRead(GifFile, &Buf, 1) != 1) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } - // fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf); - switch (Buf) { - case DESCRIPTOR_INTRODUCER: - *Type = IMAGE_DESC_RECORD_TYPE; - break; - case EXTENSION_INTRODUCER: - *Type = EXTENSION_RECORD_TYPE; - break; - case TERMINATOR_INTRODUCER: - *Type = TERMINATE_RECORD_TYPE; - break; - default: - *Type = UNDEFINED_RECORD_TYPE; - GifFile->Error = D_GIF_ERR_WRONG_RECORD; - return GIF_ERROR; - } + // fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf); + switch (Buf) { + case DESCRIPTOR_INTRODUCER: + *Type = IMAGE_DESC_RECORD_TYPE; + break; + case EXTENSION_INTRODUCER: + *Type = EXTENSION_RECORD_TYPE; + break; + case TERMINATOR_INTRODUCER: + *Type = TERMINATE_RECORD_TYPE; + break; + default: + *Type = UNDEFINED_RECORD_TYPE; + GifFile->Error = D_GIF_ERR_WRONG_RECORD; + return GIF_ERROR; + } - return GIF_OK; + return GIF_OK; } int DGifGetImageHeader(GifFileType *GifFile) { - unsigned int BitsPerPixel; - GifByteType Buf[3]; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + unsigned int BitsPerPixel; + GifByteType Buf[3]; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || - DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) { - return GIF_ERROR; - } - if (InternalRead(GifFile, Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - return GIF_ERROR; - } - BitsPerPixel = (Buf[0] & 0x07) + 1; - GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false; - - /* Setup the colormap */ - if (GifFile->Image.ColorMap) { - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - /* Does this image have local color map? */ - if (Buf[0] & 0x80) { - unsigned int i; - - GifFile->Image.ColorMap = - GifMakeMapObject(1 << BitsPerPixel, NULL); - if (GifFile->Image.ColorMap == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; } - /* Get the image local color map: */ - for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { - /* coverity[check_return] */ - if (InternalRead(GifFile, Buf, 3) != 3) { - GifFreeMapObject(GifFile->Image.ColorMap); + if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || + DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || + DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || + DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) { + return GIF_ERROR; + } + if (InternalRead(GifFile, Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; + GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; return GIF_ERROR; - } - GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; - GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; - GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } - } + BitsPerPixel = (Buf[0] & 0x07) + 1; + GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false; - Private->PixelCount = - (long)GifFile->Image.Width * (long)GifFile->Image.Height; + /* Setup the colormap */ + if (GifFile->Image.ColorMap) { + GifFreeMapObject(GifFile->Image.ColorMap); + GifFile->Image.ColorMap = NULL; + } + /* Does this image have local color map? */ + if (Buf[0] & 0x80) { + unsigned int i; - /* Reset decompress algorithm parameters. */ - return DGifSetupDecompress(GifFile); + GifFile->Image.ColorMap = + GifMakeMapObject(1 << BitsPerPixel, NULL); + if (GifFile->Image.ColorMap == NULL) { + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; + return GIF_ERROR; + } + + /* Get the image local color map: */ + for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { + /* coverity[check_return] */ + if (InternalRead(GifFile, Buf, 3) != 3) { + GifFreeMapObject(GifFile->Image.ColorMap); + GifFile->Error = D_GIF_ERR_READ_FAILED; + GifFile->Image.ColorMap = NULL; + return GIF_ERROR; + } + GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; + GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; + GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; + } + } + + Private->PixelCount = + (long)GifFile->Image.Width * (long)GifFile->Image.Height; + + /* Reset decompress algorithm parameters. */ + return DGifSetupDecompress(GifFile); } /****************************************************************************** @@ -451,133 +451,135 @@ int DGifGetImageHeader(GifFileType *GifFile) { Note it is assumed the Image desc. header has been read. ******************************************************************************/ int DGifGetImageDesc(GifFileType *GifFile) { - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - SavedImage *sp; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + SavedImage *sp; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (DGifGetImageHeader(GifFile) == GIF_ERROR) { - return GIF_ERROR; - } - - if (GifFile->SavedImages) { - SavedImage *new_saved_images = (SavedImage *)reallocarray( - GifFile->SavedImages, (GifFile->ImageCount + 1), - sizeof(SavedImage)); - if (new_saved_images == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; } - GifFile->SavedImages = new_saved_images; - } else { - if ((GifFile->SavedImages = - (SavedImage *)malloc(sizeof(SavedImage))) == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; + + if (DGifGetImageHeader(GifFile) == GIF_ERROR) { + return GIF_ERROR; } - } - sp = &GifFile->SavedImages[GifFile->ImageCount]; - memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); - if (GifFile->Image.ColorMap != NULL) { - sp->ImageDesc.ColorMap = - GifMakeMapObject(GifFile->Image.ColorMap->ColorCount, - GifFile->Image.ColorMap->Colors); - if (sp->ImageDesc.ColorMap == NULL) { - GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; - return GIF_ERROR; + if (GifFile->SavedImages) { + SavedImage *new_saved_images = (SavedImage *)reallocarray( + GifFile->SavedImages, (GifFile->ImageCount + 1), + sizeof(SavedImage)); + if (new_saved_images == NULL) { + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; + return GIF_ERROR; + } + GifFile->SavedImages = new_saved_images; + } else { + if ((GifFile->SavedImages = + (SavedImage *)malloc(sizeof(SavedImage))) == NULL) { + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; + return GIF_ERROR; + } } - } - sp->RasterBits = (unsigned char *)NULL; - sp->ExtensionBlockCount = 0; - sp->ExtensionBlocks = (ExtensionBlock *)NULL; - GifFile->ImageCount++; + sp = &GifFile->SavedImages[GifFile->ImageCount]; + memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); + if (GifFile->Image.ColorMap != NULL) { + sp->ImageDesc.ColorMap = + GifMakeMapObject(GifFile->Image.ColorMap->ColorCount, + GifFile->Image.ColorMap->Colors); + if (sp->ImageDesc.ColorMap == NULL) { + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; + return GIF_ERROR; + } + } + sp->RasterBits = (unsigned char *)NULL; + sp->ExtensionBlockCount = 0; + sp->ExtensionBlocks = (ExtensionBlock *)NULL; - return GIF_OK; + GifFile->ImageCount++; + + return GIF_OK; } /****************************************************************************** Get one full scanned line (Line) of length LineLen from GIF file. ******************************************************************************/ int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) { - GifByteType *Dummy; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifByteType *Dummy; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (!LineLen) { - LineLen = GifFile->Image.Width; - } - - if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { - GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; - return GIF_ERROR; - } - - if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { - if (Private->PixelCount == 0) { - /* We probably won't be called any more, so let's clean - * up everything before we return: need to flush out all - * the rest of image until an empty block (size 0) - * detected. We use GetCodeNext. - */ - do { - if (DGifGetCodeNext(GifFile, &Dummy) == - GIF_ERROR) { - return GIF_ERROR; - } - } while (Dummy != NULL); + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + + if (!LineLen) { + LineLen = GifFile->Image.Width; + } + + if (LineLen < 0 || Private->PixelCount < (unsigned long)LineLen) { + GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; + return GIF_ERROR; + } + Private->PixelCount -= LineLen; + + if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { + if (Private->PixelCount == 0) { + /* We probably won't be called any more, so let's clean + * up everything before we return: need to flush out all + * the rest of image until an empty block (size 0) + * detected. We use GetCodeNext. + */ + do { + if (DGifGetCodeNext(GifFile, &Dummy) == + GIF_ERROR) { + return GIF_ERROR; + } + } while (Dummy != NULL); + } + return GIF_OK; + } else { + return GIF_ERROR; } - return GIF_OK; - } else { - return GIF_ERROR; - } } /****************************************************************************** Put one pixel (Pixel) into GIF file. ******************************************************************************/ int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) { - GifByteType *Dummy; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifByteType *Dummy; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - if (--Private->PixelCount > 0xffff0000UL) { - GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; - return GIF_ERROR; - } - - if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { - if (Private->PixelCount == 0) { - /* We probably won't be called any more, so let's clean - * up everything before we return: need to flush out all - * the rest of image until an empty block (size 0) - * detected. We use GetCodeNext. - */ - do { - if (DGifGetCodeNext(GifFile, &Dummy) == - GIF_ERROR) { - return GIF_ERROR; - } - } while (Dummy != NULL); + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } + if (Private->PixelCount == 0) { + GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; + return GIF_ERROR; + } + Private->PixelCount --; + + if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { + if (Private->PixelCount == 0) { + /* We probably won't be called any more, so let's clean + * up everything before we return: need to flush out all + * the rest of image until an empty block (size 0) + * detected. We use GetCodeNext. + */ + do { + if (DGifGetCodeNext(GifFile, &Dummy) == + GIF_ERROR) { + return GIF_ERROR; + } + } while (Dummy != NULL); + } + return GIF_OK; + } else { + return GIF_ERROR; } - return GIF_OK; - } else { - return GIF_ERROR; - } } /****************************************************************************** @@ -589,26 +591,26 @@ int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) { ******************************************************************************/ int DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) { - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - // fprintf(stderr, "### -> DGifGetExtension:\n"); - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } + // fprintf(stderr, "### -> DGifGetExtension:\n"); + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } - /* coverity[check_return] */ - if (InternalRead(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - *ExtCode = Buf; - // fprintf(stderr, "### <- DGifGetExtension: %02x, about to call - // next\n", Buf); + /* coverity[check_return] */ + if (InternalRead(GifFile, &Buf, 1) != 1) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + *ExtCode = Buf; + // fprintf(stderr, "### <- DGifGetExtension: %02x, about to call + // next\n", Buf); - return DGifGetExtensionNext(GifFile, Extension); + return DGifGetExtensionNext(GifFile, Extension); } /****************************************************************************** @@ -617,31 +619,31 @@ int DGifGetExtension(GifFileType *GifFile, int *ExtCode, The Extension should NOT be freed by the user (not dynamically allocated). ******************************************************************************/ int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) { - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - // fprintf(stderr, "### -> DGifGetExtensionNext\n"); - if (InternalRead(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - // fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf); - - if (Buf > 0) { - *Extension = Private->Buf; /* Use private unused buffer. */ - (*Extension)[0] = - Buf; /* Pascal strings notation (pos. 0 is len.). */ - /* coverity[tainted_data,check_return] */ - if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; + // fprintf(stderr, "### -> DGifGetExtensionNext\n"); + if (InternalRead(GifFile, &Buf, 1) != 1) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; } - } else { - *Extension = NULL; - } - // fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension); + // fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf); - return GIF_OK; + if (Buf > 0) { + *Extension = Private->Buf; /* Use private unused buffer. */ + (*Extension)[0] = + Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data,check_return] */ + if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + } else { + *Extension = NULL; + } + // fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension); + + return GIF_OK; } /****************************************************************************** @@ -651,21 +653,21 @@ int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) { int DGifExtensionToGCB(const size_t GifExtensionLength, const GifByteType *GifExtension, GraphicsControlBlock *GCB) { - if (GifExtensionLength != 4) { - return GIF_ERROR; - } + if (GifExtensionLength != 4) { + return GIF_ERROR; + } - GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07; - GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0; - GCB->DelayTime = - UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); - if (GifExtension[0] & 0x01) { - GCB->TransparentColor = (int)GifExtension[3]; - } else { - GCB->TransparentColor = NO_TRANSPARENT_COLOR; - } + GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07; + GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0; + GCB->DelayTime = + UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); + if (GifExtension[0] & 0x01) { + GCB->TransparentColor = (int)GifExtension[3]; + } else { + GCB->TransparentColor = NO_TRANSPARENT_COLOR; + } - return GIF_OK; + return GIF_OK; } /****************************************************************************** @@ -674,101 +676,101 @@ int DGifExtensionToGCB(const size_t GifExtensionLength, int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex, GraphicsControlBlock *GCB) { - int i; + int i; - if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) { - return GIF_ERROR; - } - - GCB->DisposalMode = DISPOSAL_UNSPECIFIED; - GCB->UserInputFlag = false; - GCB->DelayTime = 0; - GCB->TransparentColor = NO_TRANSPARENT_COLOR; - - for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; - i++) { - ExtensionBlock *ep = - &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; - if (ep->Function == GRAPHICS_EXT_FUNC_CODE) { - return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, - GCB); + if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) { + return GIF_ERROR; } - } - return GIF_ERROR; + GCB->DisposalMode = DISPOSAL_UNSPECIFIED; + GCB->UserInputFlag = false; + GCB->DelayTime = 0; + GCB->TransparentColor = NO_TRANSPARENT_COLOR; + + for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; + i++) { + ExtensionBlock *ep = + &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; + if (ep->Function == GRAPHICS_EXT_FUNC_CODE) { + return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, + GCB); + } + } + + return GIF_ERROR; } /****************************************************************************** This routine should be called last, to close the GIF file. ******************************************************************************/ int DGifCloseFile(GifFileType *GifFile, int *ErrorCode) { - GifFilePrivateType *Private; + GifFilePrivateType *Private; - if (GifFile == NULL || GifFile->Private == NULL) { - return GIF_ERROR; - } - - if (GifFile->Image.ColorMap) { - GifFreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; - } - - if (GifFile->SColorMap) { - GifFreeMapObject(GifFile->SColorMap); - GifFile->SColorMap = NULL; - } - - if (GifFile->SavedImages) { - GifFreeSavedImages(GifFile); - GifFile->SavedImages = NULL; - } - - GifFreeExtensions(&GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks); - - Private = (GifFilePrivateType *)GifFile->Private; - - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - if (ErrorCode != NULL) { - *ErrorCode = D_GIF_ERR_NOT_READABLE; + if (GifFile == NULL || GifFile->Private == NULL) { + return GIF_ERROR; } + + if (GifFile->Image.ColorMap) { + GifFreeMapObject(GifFile->Image.ColorMap); + GifFile->Image.ColorMap = NULL; + } + + if (GifFile->SColorMap) { + GifFreeMapObject(GifFile->SColorMap); + GifFile->SColorMap = NULL; + } + + if (GifFile->SavedImages) { + GifFreeSavedImages(GifFile); + GifFile->SavedImages = NULL; + } + + GifFreeExtensions(&GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks); + + Private = (GifFilePrivateType *)GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + if (ErrorCode != NULL) { + *ErrorCode = D_GIF_ERR_NOT_READABLE; + } + free((char *)GifFile->Private); + free(GifFile); + return GIF_ERROR; + } + + if (Private->File && (fclose(Private->File) != 0)) { + if (ErrorCode != NULL) { + *ErrorCode = D_GIF_ERR_CLOSE_FAILED; + } + free((char *)GifFile->Private); + free(GifFile); + return GIF_ERROR; + } + free((char *)GifFile->Private); free(GifFile); - return GIF_ERROR; - } - - if (Private->File && (fclose(Private->File) != 0)) { if (ErrorCode != NULL) { - *ErrorCode = D_GIF_ERR_CLOSE_FAILED; + *ErrorCode = D_GIF_SUCCEEDED; } - free((char *)GifFile->Private); - free(GifFile); - return GIF_ERROR; - } - - free((char *)GifFile->Private); - free(GifFile); - if (ErrorCode != NULL) { - *ErrorCode = D_GIF_SUCCEEDED; - } - return GIF_OK; + return GIF_OK; } /****************************************************************************** Get 2 bytes (word) from the given file: ******************************************************************************/ static int DGifGetWord(GifFileType *GifFile, GifWord *Word) { - unsigned char c[2]; + unsigned char c[2]; - /* coverity[check_return] */ - if (InternalRead(GifFile, c, 2) != 2) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } + /* coverity[check_return] */ + if (InternalRead(GifFile, c, 2) != 2) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } - *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]); - return GIF_OK; + *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]); + return GIF_OK; } /****************************************************************************** @@ -779,17 +781,17 @@ static int DGifGetWord(GifFileType *GifFile, GifWord *Word) { The block should NOT be freed by the user (not dynamically allocated). ******************************************************************************/ int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) { - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; + return GIF_ERROR; + } - *CodeSize = Private->BitsPerPixel; + *CodeSize = Private->BitsPerPixel; - return DGifGetCodeNext(GifFile, CodeBlock); + return DGifGetCodeNext(GifFile, CodeBlock); } /****************************************************************************** @@ -798,78 +800,78 @@ int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) { The block should NOT be freed by the user (not dynamically allocated). ******************************************************************************/ int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) { - GifByteType Buf; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifByteType Buf; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - /* coverity[tainted_data_argument] */ - /* coverity[check_return] */ - if (InternalRead(GifFile, &Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - - /* coverity[lower_bounds] */ - if (Buf > 0) { - *CodeBlock = Private->Buf; /* Use private unused buffer. */ - (*CodeBlock)[0] = - Buf; /* Pascal strings notation (pos. 0 is len.). */ - /* coverity[tainted_data] */ - if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; + /* coverity[tainted_data_argument] */ + /* coverity[check_return] */ + if (InternalRead(GifFile, &Buf, 1) != 1) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; } - } else { - *CodeBlock = NULL; - Private->Buf[0] = 0; /* Make sure the buffer is empty! */ - Private->PixelCount = - 0; /* And local info. indicate image read. */ - } - return GIF_OK; + /* coverity[lower_bounds] */ + if (Buf > 0) { + *CodeBlock = Private->Buf; /* Use private unused buffer. */ + (*CodeBlock)[0] = + Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data] */ + if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + } else { + *CodeBlock = NULL; + Private->Buf[0] = 0; /* Make sure the buffer is empty! */ + Private->PixelCount = + 0; /* And local info. indicate image read. */ + } + + return GIF_OK; } /****************************************************************************** Setup the LZ decompression for this image: ******************************************************************************/ static int DGifSetupDecompress(GifFileType *GifFile) { - int i, BitsPerPixel; - GifByteType CodeSize; - GifPrefixType *Prefix; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + int i, BitsPerPixel; + GifByteType CodeSize; + GifPrefixType *Prefix; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - /* coverity[check_return] */ - if (InternalRead(GifFile, &CodeSize, 1) < - 1) { /* Read Code size from file. */ - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; /* Failed to read Code size. */ - } - BitsPerPixel = CodeSize; + /* coverity[check_return] */ + if (InternalRead(GifFile, &CodeSize, 1) < + 1) { /* Read Code size from file. */ + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; /* Failed to read Code size. */ + } + BitsPerPixel = CodeSize; - /* this can only happen on a severely malformed GIF */ - if (BitsPerPixel > 8) { - GifFile->Error = - D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */ - return GIF_ERROR; /* Failed to read Code size. */ - } + /* this can only happen on a severely malformed GIF */ + if (BitsPerPixel > 8) { + GifFile->Error = + D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */ + return GIF_ERROR; /* Failed to read Code size. */ + } - Private->Buf[0] = 0; /* Input Buffer empty. */ - Private->BitsPerPixel = BitsPerPixel; - Private->ClearCode = (1 << BitsPerPixel); - Private->EOFCode = Private->ClearCode + 1; - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ - Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ - Private->StackPtr = 0; /* No pixels on the pixel stack. */ - Private->LastCode = NO_SUCH_CODE; - Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ - Private->CrntShiftDWord = 0; + Private->Buf[0] = 0; /* Input Buffer empty. */ + Private->BitsPerPixel = BitsPerPixel; + Private->ClearCode = (1 << BitsPerPixel); + Private->EOFCode = Private->ClearCode + 1; + Private->RunningCode = Private->EOFCode + 1; + Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */ + Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */ + Private->StackPtr = 0; /* No pixels on the pixel stack. */ + Private->LastCode = NO_SUCH_CODE; + Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */ + Private->CrntShiftDWord = 0; - Prefix = Private->Prefix; - for (i = 0; i <= LZ_MAX_CODE; i++) { - Prefix[i] = NO_SUCH_CODE; - } + Prefix = Private->Prefix; + for (i = 0; i <= LZ_MAX_CODE; i++) { + Prefix[i] = NO_SUCH_CODE; + } - return GIF_OK; + return GIF_OK; } /****************************************************************************** @@ -880,147 +882,147 @@ static int DGifSetupDecompress(GifFileType *GifFile) { ******************************************************************************/ static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) { - int i = 0; - int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; - GifByteType *Stack, *Suffix; - GifPrefixType *Prefix; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + int i = 0; + int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; + GifByteType *Stack, *Suffix; + GifPrefixType *Prefix; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - StackPtr = Private->StackPtr; - Prefix = Private->Prefix; - Suffix = Private->Suffix; - Stack = Private->Stack; - EOFCode = Private->EOFCode; - ClearCode = Private->ClearCode; - LastCode = Private->LastCode; + StackPtr = Private->StackPtr; + Prefix = Private->Prefix; + Suffix = Private->Suffix; + Stack = Private->Stack; + EOFCode = Private->EOFCode; + ClearCode = Private->ClearCode; + LastCode = Private->LastCode; - if (StackPtr > LZ_MAX_CODE) { - return GIF_ERROR; - } - - if (StackPtr != 0) { - /* Let pop the stack off before continueing to read the GIF - * file: */ - while (StackPtr != 0 && i < LineLen) { - Line[i++] = Stack[--StackPtr]; - } - } - - while (i < LineLen) { /* Decode LineLen items. */ - if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) { - return GIF_ERROR; + if (StackPtr > LZ_MAX_CODE) { + return GIF_ERROR; } - if (CrntCode == EOFCode) { - /* Note however that usually we will not be here as we - * will stop decoding as soon as we got all the pixel, - * or EOF code will not be read at all, and - * DGifGetLine/Pixel clean everything. */ - GifFile->Error = D_GIF_ERR_EOF_TOO_SOON; - return GIF_ERROR; - } else if (CrntCode == ClearCode) { - /* We need to start over again: */ - for (j = 0; j <= LZ_MAX_CODE; j++) { - Prefix[j] = NO_SUCH_CODE; - } - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - LastCode = Private->LastCode = NO_SUCH_CODE; - } else { - /* Its regular code - if in pixel range simply add it to - * output stream, otherwise trace to codes linked list - * until the prefix is in pixel range: */ - if (CrntCode < ClearCode) { - /* This is simple - its pixel scalar, so add it - * to output: */ - Line[i++] = CrntCode; - } else { - /* Its a code to needed to be traced: trace the - * linked list until the prefix is a pixel, - * while pushing the suffix pixels on our stack. - * If we done, pop the stack in reverse (thats - * what stack is good for!) order to output. */ - if (Prefix[CrntCode] == NO_SUCH_CODE) { - CrntPrefix = LastCode; - - /* Only allowed if CrntCode is exactly - * the running code: In that case - * CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the - * suffix char is exactly the prefix of - * last code! */ - if (CrntCode == - Private->RunningCode - 2) { - Suffix[Private->RunningCode - - 2] = Stack[StackPtr++] = - DGifGetPrefixChar( - Prefix, LastCode, - ClearCode); - } else { - Suffix[Private->RunningCode - - 2] = Stack[StackPtr++] = - DGifGetPrefixChar( - Prefix, CrntCode, - ClearCode); - } - } else { - CrntPrefix = CrntCode; - } - - /* Now (if image is O.K.) we should not get a - * NO_SUCH_CODE during the trace. As we might - * loop forever, in case of defective image, we - * use StackPtr as loop counter and stop before - * overflowing Stack[]. */ - while (StackPtr < LZ_MAX_CODE && - CrntPrefix > ClearCode && - CrntPrefix <= LZ_MAX_CODE) { - Stack[StackPtr++] = Suffix[CrntPrefix]; - CrntPrefix = Prefix[CrntPrefix]; - } - if (StackPtr >= LZ_MAX_CODE || - CrntPrefix > LZ_MAX_CODE) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - /* Push the last character on stack: */ - Stack[StackPtr++] = CrntPrefix; - - /* Now lets pop all the stack into output: */ + if (StackPtr != 0) { + /* Let pop the stack off before continueing to read the GIF + * file: */ while (StackPtr != 0 && i < LineLen) { - Line[i++] = Stack[--StackPtr]; + Line[i++] = Stack[--StackPtr]; } - } - if (LastCode != NO_SUCH_CODE && - Private->RunningCode - 2 < (LZ_MAX_CODE + 1) && - Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { - Prefix[Private->RunningCode - 2] = LastCode; - - if (CrntCode == Private->RunningCode - 2) { - /* Only allowed if CrntCode is exactly - * the running code: In that case - * CrntCode = XXXCode, CrntCode or the - * prefix code is last code and the - * suffix char is exactly the prefix of - * last code! */ - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, LastCode, - ClearCode); - } else { - Suffix[Private->RunningCode - 2] = - DGifGetPrefixChar(Prefix, CrntCode, - ClearCode); - } - } - LastCode = CrntCode; } - } - Private->LastCode = LastCode; - Private->StackPtr = StackPtr; + while (i < LineLen) { /* Decode LineLen items. */ + if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) { + return GIF_ERROR; + } - return GIF_OK; + if (CrntCode == EOFCode) { + /* Note however that usually we will not be here as we + * will stop decoding as soon as we got all the pixel, + * or EOF code will not be read at all, and + * DGifGetLine/Pixel clean everything. */ + GifFile->Error = D_GIF_ERR_EOF_TOO_SOON; + return GIF_ERROR; + } else if (CrntCode == ClearCode) { + /* We need to start over again: */ + for (j = 0; j <= LZ_MAX_CODE; j++) { + Prefix[j] = NO_SUCH_CODE; + } + Private->RunningCode = Private->EOFCode + 1; + Private->RunningBits = Private->BitsPerPixel + 1; + Private->MaxCode1 = 1 << Private->RunningBits; + LastCode = Private->LastCode = NO_SUCH_CODE; + } else { + /* Its regular code - if in pixel range simply add it to + * output stream, otherwise trace to codes linked list + * until the prefix is in pixel range: */ + if (CrntCode < ClearCode) { + /* This is simple - its pixel scalar, so add it + * to output: */ + Line[i++] = CrntCode; + } else { + /* Its a code to needed to be traced: trace the + * linked list until the prefix is a pixel, + * while pushing the suffix pixels on our stack. + * If we done, pop the stack in reverse (thats + * what stack is good for!) order to output. */ + if (Prefix[CrntCode] == NO_SUCH_CODE) { + CrntPrefix = LastCode; + + /* Only allowed if CrntCode is exactly + * the running code: In that case + * CrntCode = XXXCode, CrntCode or the + * prefix code is last code and the + * suffix char is exactly the prefix of + * last code! */ + if (CrntCode == + Private->RunningCode - 2) { + Suffix[Private->RunningCode - + 2] = Stack[StackPtr++] = + DGifGetPrefixChar( + Prefix, LastCode, + ClearCode); + } else { + Suffix[Private->RunningCode - + 2] = Stack[StackPtr++] = + DGifGetPrefixChar( + Prefix, CrntCode, + ClearCode); + } + } else { + CrntPrefix = CrntCode; + } + + /* Now (if image is O.K.) we should not get a + * NO_SUCH_CODE during the trace. As we might + * loop forever, in case of defective image, we + * use StackPtr as loop counter and stop before + * overflowing Stack[]. */ + while (StackPtr < LZ_MAX_CODE && + CrntPrefix > ClearCode && + CrntPrefix <= LZ_MAX_CODE) { + Stack[StackPtr++] = Suffix[CrntPrefix]; + CrntPrefix = Prefix[CrntPrefix]; + } + if (StackPtr >= LZ_MAX_CODE || + CrntPrefix > LZ_MAX_CODE) { + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; + return GIF_ERROR; + } + /* Push the last character on stack: */ + Stack[StackPtr++] = CrntPrefix; + + /* Now lets pop all the stack into output: */ + while (StackPtr != 0 && i < LineLen) { + Line[i++] = Stack[--StackPtr]; + } + } + if (LastCode != NO_SUCH_CODE && + Private->RunningCode - 2 < (LZ_MAX_CODE + 1) && + Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { + Prefix[Private->RunningCode - 2] = LastCode; + + if (CrntCode == Private->RunningCode - 2) { + /* Only allowed if CrntCode is exactly + * the running code: In that case + * CrntCode = XXXCode, CrntCode or the + * prefix code is last code and the + * suffix char is exactly the prefix of + * last code! */ + Suffix[Private->RunningCode - 2] = + DGifGetPrefixChar(Prefix, LastCode, + ClearCode); + } else { + Suffix[Private->RunningCode - 2] = + DGifGetPrefixChar(Prefix, CrntCode, + ClearCode); + } + } + LastCode = CrntCode; + } + } + + Private->LastCode = LastCode; + Private->StackPtr = StackPtr; + + return GIF_OK; } /****************************************************************************** @@ -1031,15 +1033,15 @@ static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, ******************************************************************************/ static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, int ClearCode) { - int i = 0; + int i = 0; - while (Code > ClearCode && i++ <= LZ_MAX_CODE) { - if (Code > LZ_MAX_CODE) { - return NO_SUCH_CODE; + while (Code > ClearCode && i++ <= LZ_MAX_CODE) { + if (Code > LZ_MAX_CODE) { + return NO_SUCH_CODE; + } + Code = Prefix[Code]; } - Code = Prefix[Code]; - } - return Code; + return Code; } /****************************************************************************** @@ -1047,37 +1049,37 @@ static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, (12bits), or to -1 if EOF code is returned. ******************************************************************************/ int DGifGetLZCodes(GifFileType *GifFile, int *Code) { - GifByteType *CodeBlock; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifByteType *CodeBlock; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; - } - - if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) { - return GIF_ERROR; - } - - if (*Code == Private->EOFCode) { - /* Skip rest of codes (hopefully only NULL terminating block): - */ - do { - if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) { + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; - } - } while (CodeBlock != NULL); + } - *Code = -1; - } else if (*Code == Private->ClearCode) { - /* We need to start over again: */ - Private->RunningCode = Private->EOFCode + 1; - Private->RunningBits = Private->BitsPerPixel + 1; - Private->MaxCode1 = 1 << Private->RunningBits; - } + if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) { + return GIF_ERROR; + } - return GIF_OK; + if (*Code == Private->EOFCode) { + /* Skip rest of codes (hopefully only NULL terminating block): + */ + do { + if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) { + return GIF_ERROR; + } + } while (CodeBlock != NULL); + + *Code = -1; + } else if (*Code == Private->ClearCode) { + /* We need to start over again: */ + Private->RunningCode = Private->EOFCode + 1; + Private->RunningBits = Private->BitsPerPixel + 1; + Private->MaxCode1 = 1 << Private->RunningBits; + } + + return GIF_OK; } /****************************************************************************** @@ -1087,47 +1089,47 @@ int DGifGetLZCodes(GifFileType *GifFile, int *Code) { Returns GIF_OK if read successfully. ******************************************************************************/ static int DGifDecompressInput(GifFileType *GifFile, int *Code) { - static const unsigned short CodeMasks[] = { - 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, - 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff}; + static const unsigned short CodeMasks[] = { + 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, + 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff}; - GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - GifByteType NextByte; + GifByteType NextByte; - /* The image can't contain more than LZ_BITS per code. */ - if (Private->RunningBits > LZ_BITS) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } - - while (Private->CrntShiftState < Private->RunningBits) { - /* Needs to get more bytes from input stream for next code: */ - if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == - GIF_ERROR) { - return GIF_ERROR; + /* The image can't contain more than LZ_BITS per code. */ + if (Private->RunningBits > LZ_BITS) { + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; + return GIF_ERROR; } - Private->CrntShiftDWord |= ((unsigned long)NextByte) - << Private->CrntShiftState; - Private->CrntShiftState += 8; - } - *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; - Private->CrntShiftDWord >>= Private->RunningBits; - Private->CrntShiftState -= Private->RunningBits; + while (Private->CrntShiftState < Private->RunningBits) { + /* Needs to get more bytes from input stream for next code: */ + if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == + GIF_ERROR) { + return GIF_ERROR; + } + Private->CrntShiftDWord |= ((unsigned long)NextByte) + << Private->CrntShiftState; + Private->CrntShiftState += 8; + } + *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; - /* If code cannot fit into RunningBits bits, must raise its size. Note - * however that codes above 4095 are used for special signaling. - * If we're using LZ_BITS bits already and we're at the max code, just - * keep using the table as it is, don't increment Private->RunningCode. - */ - if (Private->RunningCode < LZ_MAX_CODE + 2 && - ++Private->RunningCode > Private->MaxCode1 && - Private->RunningBits < LZ_BITS) { - Private->MaxCode1 <<= 1; - Private->RunningBits++; - } - return GIF_OK; + Private->CrntShiftDWord >>= Private->RunningBits; + Private->CrntShiftState -= Private->RunningBits; + + /* If code cannot fit into RunningBits bits, must raise its size. Note + * however that codes above 4095 are used for special signaling. + * If we're using LZ_BITS bits already and we're at the max code, just + * keep using the table as it is, don't increment Private->RunningCode. + */ + if (Private->RunningCode < LZ_MAX_CODE + 2 && + ++Private->RunningCode > Private->MaxCode1 && + Private->RunningBits < LZ_BITS) { + Private->MaxCode1 <<= 1; + Private->RunningBits++; + } + return GIF_OK; } /****************************************************************************** @@ -1138,34 +1140,34 @@ static int DGifDecompressInput(GifFileType *GifFile, int *Code) { ******************************************************************************/ static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) { - if (Buf[0] == 0) { - /* Needs to read the next buffer - this one is empty: */ - /* coverity[check_return] */ - if (InternalRead(GifFile, Buf, 1) != 1) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - /* There shouldn't be any empty data blocks here as the LZW spec - * says the LZW termination code should come first. Therefore - * we shouldn't be inside this routine at that point. - */ if (Buf[0] == 0) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; + /* Needs to read the next buffer - this one is empty: */ + /* coverity[check_return] */ + if (InternalRead(GifFile, Buf, 1) != 1) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + /* There shouldn't be any empty data blocks here as the LZW spec + * says the LZW termination code should come first. Therefore + * we shouldn't be inside this routine at that point. + */ + if (Buf[0] == 0) { + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; + return GIF_ERROR; + } + if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) { + GifFile->Error = D_GIF_ERR_READ_FAILED; + return GIF_ERROR; + } + *NextByte = Buf[1]; + Buf[1] = 2; /* We use now the second place as last char read! */ + Buf[0]--; + } else { + *NextByte = Buf[Buf[1]++]; + Buf[0]--; } - if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) { - GifFile->Error = D_GIF_ERR_READ_FAILED; - return GIF_ERROR; - } - *NextByte = Buf[1]; - Buf[1] = 2; /* We use now the second place as last char read! */ - Buf[0]--; - } else { - *NextByte = Buf[Buf[1]++]; - Buf[0]--; - } - return GIF_OK; + return GIF_OK; } /****************************************************************************** @@ -1175,17 +1177,20 @@ static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, SavedImages may point to the spoilt image and null pointer buffers. *******************************************************************************/ void DGifDecreaseImageCounter(GifFileType *GifFile) { - GifFile->ImageCount--; - if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) { - free(GifFile->SavedImages[GifFile->ImageCount].RasterBits); - } + GifFile->ImageCount--; + if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) { + free(GifFile->SavedImages[GifFile->ImageCount].RasterBits); + } + if (GifFile->SavedImages[GifFile->ImageCount].ImageDesc.ColorMap != NULL) { + GifFreeMapObject(GifFile->SavedImages[GifFile->ImageCount].ImageDesc.ColorMap); + } - // Realloc array according to the new image counter. - SavedImage *correct_saved_images = (SavedImage *)reallocarray( - GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage)); - if (correct_saved_images != NULL) { - GifFile->SavedImages = correct_saved_images; - } + // Realloc array according to the new image counter. + SavedImage *correct_saved_images = (SavedImage *)reallocarray( + GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage)); + if (correct_saved_images != NULL) { + GifFile->SavedImages = correct_saved_images; + } } /****************************************************************************** @@ -1194,143 +1199,143 @@ void DGifDecreaseImageCounter(GifFileType *GifFile) { first to initialize I/O. Its inverse is EGifSpew(). *******************************************************************************/ int DGifSlurp(GifFileType *GifFile) { - size_t ImageSize; - GifRecordType RecordType; - SavedImage *sp; - GifByteType *ExtData; - int ExtFunction; + size_t ImageSize; + GifRecordType RecordType; + SavedImage *sp; + GifByteType *ExtData; + int ExtFunction; - GifFile->ExtensionBlocks = NULL; - GifFile->ExtensionBlockCount = 0; + GifFile->ExtensionBlocks = NULL; + GifFile->ExtensionBlockCount = 0; - do { - if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { - return (GIF_ERROR); - } + do { + if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { + return (GIF_ERROR); + } - switch (RecordType) { - case IMAGE_DESC_RECORD_TYPE: - if (DGifGetImageDesc(GifFile) == GIF_ERROR) { - return (GIF_ERROR); - } - - sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; - /* Allocate memory for the image */ - if (sp->ImageDesc.Width <= 0 || - sp->ImageDesc.Height <= 0 || - sp->ImageDesc.Width > - (INT_MAX / sp->ImageDesc.Height)) { - DGifDecreaseImageCounter(GifFile); - return GIF_ERROR; - } - ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; - - if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { - DGifDecreaseImageCounter(GifFile); - return GIF_ERROR; - } - sp->RasterBits = (unsigned char *)reallocarray( - NULL, ImageSize, sizeof(GifPixelType)); - - if (sp->RasterBits == NULL) { - DGifDecreaseImageCounter(GifFile); - return GIF_ERROR; - } - - if (sp->ImageDesc.Interlace) { - int i, j; - /* - * The way an interlaced image should be read - - * offsets and jumps... - */ - static const int InterlacedOffset[] = {0, 4, 2, - 1}; - static const int InterlacedJumps[] = {8, 8, 4, - 2}; - /* Need to perform 4 passes on the image */ - for (i = 0; i < 4; i++) { - for (j = InterlacedOffset[i]; - j < sp->ImageDesc.Height; - j += InterlacedJumps[i]) { - if (DGifGetLine( - GifFile, - sp->RasterBits + - j * sp->ImageDesc - .Width, - sp->ImageDesc.Width) == - GIF_ERROR) { - DGifDecreaseImageCounter( - GifFile); - return GIF_ERROR; + switch (RecordType) { + case IMAGE_DESC_RECORD_TYPE: + if (DGifGetImageDesc(GifFile) == GIF_ERROR) { + return (GIF_ERROR); } - } + + sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; + /* Allocate memory for the image */ + if (sp->ImageDesc.Width <= 0 || + sp->ImageDesc.Height <= 0 || + sp->ImageDesc.Width > + (INT_MAX / sp->ImageDesc.Height)) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; + + if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + sp->RasterBits = (unsigned char *)reallocarray( + NULL, ImageSize, sizeof(GifPixelType)); + + if (sp->RasterBits == NULL) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + + if (sp->ImageDesc.Interlace) { + int i, j; + /* + * The way an interlaced image should be read - + * offsets and jumps... + */ + static const int InterlacedOffset[] = {0, 4, 2, + 1}; + static const int InterlacedJumps[] = {8, 8, 4, + 2}; + /* Need to perform 4 passes on the image */ + for (i = 0; i < 4; i++) { + for (j = InterlacedOffset[i]; + j < sp->ImageDesc.Height; + j += InterlacedJumps[i]) { + if (DGifGetLine( + GifFile, + sp->RasterBits + + j * sp->ImageDesc + .Width, + sp->ImageDesc.Width) == + GIF_ERROR) { + DGifDecreaseImageCounter( + GifFile); + return GIF_ERROR; + } + } + } + } else { + if (DGifGetLine(GifFile, sp->RasterBits, + ImageSize) == GIF_ERROR) { + DGifDecreaseImageCounter(GifFile); + return GIF_ERROR; + } + } + + if (GifFile->ExtensionBlocks) { + sp->ExtensionBlocks = GifFile->ExtensionBlocks; + sp->ExtensionBlockCount = + GifFile->ExtensionBlockCount; + + GifFile->ExtensionBlocks = NULL; + GifFile->ExtensionBlockCount = 0; + } + break; + + case EXTENSION_RECORD_TYPE: + if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) == + GIF_ERROR) { + return (GIF_ERROR); + } + /* Create an extension block with our data */ + if (ExtData != NULL) { + if (GifAddExtensionBlock( + &GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks, ExtFunction, + ExtData[0], &ExtData[1]) == GIF_ERROR) { + return (GIF_ERROR); + } + } + for (;;) { + if (DGifGetExtensionNext(GifFile, &ExtData) == + GIF_ERROR) { + return (GIF_ERROR); + } + if (ExtData == NULL) { + break; + } + /* Continue the extension block */ + if (GifAddExtensionBlock( + &GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks, + CONTINUE_EXT_FUNC_CODE, ExtData[0], + &ExtData[1]) == GIF_ERROR) { + return (GIF_ERROR); + } + } + break; + + case TERMINATE_RECORD_TYPE: + break; + + default: /* Should be trapped by DGifGetRecordType */ + break; } - } else { - if (DGifGetLine(GifFile, sp->RasterBits, - ImageSize) == GIF_ERROR) { - DGifDecreaseImageCounter(GifFile); - return GIF_ERROR; - } - } + } while (RecordType != TERMINATE_RECORD_TYPE); - if (GifFile->ExtensionBlocks) { - sp->ExtensionBlocks = GifFile->ExtensionBlocks; - sp->ExtensionBlockCount = - GifFile->ExtensionBlockCount; - - GifFile->ExtensionBlocks = NULL; - GifFile->ExtensionBlockCount = 0; - } - break; - - case EXTENSION_RECORD_TYPE: - if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) == - GIF_ERROR) { + /* Sanity check for corrupted file */ + if (GifFile->ImageCount == 0) { + GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR; return (GIF_ERROR); - } - /* Create an extension block with our data */ - if (ExtData != NULL) { - if (GifAddExtensionBlock( - &GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, ExtFunction, - ExtData[0], &ExtData[1]) == GIF_ERROR) { - return (GIF_ERROR); - } - } - for (;;) { - if (DGifGetExtensionNext(GifFile, &ExtData) == - GIF_ERROR) { - return (GIF_ERROR); - } - if (ExtData == NULL) { - break; - } - /* Continue the extension block */ - if (GifAddExtensionBlock( - &GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, - CONTINUE_EXT_FUNC_CODE, ExtData[0], - &ExtData[1]) == GIF_ERROR) { - return (GIF_ERROR); - } - } - break; - - case TERMINATE_RECORD_TYPE: - break; - - default: /* Should be trapped by DGifGetRecordType */ - break; } - } while (RecordType != TERMINATE_RECORD_TYPE); - /* Sanity check for corrupted file */ - if (GifFile->ImageCount == 0) { - GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR; - return (GIF_ERROR); - } - - return (GIF_OK); + return (GIF_OK); } /* end */ diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c b/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c index 3b6785f7c63..a3cc03b8865 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c @@ -26,9 +26,9 @@ gif_err.c - handle error reporting for the GIF library. -SPDX-License-Identifier: MIT - ****************************************************************************/ +// SPDX-License-Identifier: MIT +// SPDX-File-Copyright-Txt: (C) Copyright 1989 Gershon Elber #include @@ -39,83 +39,83 @@ SPDX-License-Identifier: MIT Return a string description of the last GIF error *****************************************************************************/ const char *GifErrorString(int ErrorCode) { - const char *Err; + const char *Err; - switch (ErrorCode) { - case E_GIF_ERR_OPEN_FAILED: - Err = "Failed to open given file"; - break; - case E_GIF_ERR_WRITE_FAILED: - Err = "Failed to write to given file"; - break; - case E_GIF_ERR_HAS_SCRN_DSCR: - Err = "Screen descriptor has already been set"; - break; - case E_GIF_ERR_HAS_IMAG_DSCR: - Err = "Image descriptor is still active"; - break; - case E_GIF_ERR_NO_COLOR_MAP: - Err = "Neither global nor local color map"; - break; - case E_GIF_ERR_DATA_TOO_BIG: - Err = "Number of pixels bigger than width * height"; - break; - case E_GIF_ERR_NOT_ENOUGH_MEM: - Err = "Failed to allocate required memory"; - break; - case E_GIF_ERR_DISK_IS_FULL: - Err = "Write failed (disk full?)"; - break; - case E_GIF_ERR_CLOSE_FAILED: - Err = "Failed to close given file"; - break; - case E_GIF_ERR_NOT_WRITEABLE: - Err = "Given file was not opened for write"; - break; - case D_GIF_ERR_OPEN_FAILED: - Err = "Failed to open given file"; - break; - case D_GIF_ERR_READ_FAILED: - Err = "Failed to read from given file"; - break; - case D_GIF_ERR_NOT_GIF_FILE: - Err = "Data is not in GIF format"; - break; - case D_GIF_ERR_NO_SCRN_DSCR: - Err = "No screen descriptor detected"; - break; - case D_GIF_ERR_NO_IMAG_DSCR: - Err = "No Image Descriptor detected"; - break; - case D_GIF_ERR_NO_COLOR_MAP: - Err = "Neither global nor local color map"; - break; - case D_GIF_ERR_WRONG_RECORD: - Err = "Wrong record type detected"; - break; - case D_GIF_ERR_DATA_TOO_BIG: - Err = "Number of pixels bigger than width * height"; - break; - case D_GIF_ERR_NOT_ENOUGH_MEM: - Err = "Failed to allocate required memory"; - break; - case D_GIF_ERR_CLOSE_FAILED: - Err = "Failed to close given file"; - break; - case D_GIF_ERR_NOT_READABLE: - Err = "Given file was not opened for read"; - break; - case D_GIF_ERR_IMAGE_DEFECT: - Err = "Image is defective, decoding aborted"; - break; - case D_GIF_ERR_EOF_TOO_SOON: - Err = "Image EOF detected before image complete"; - break; - default: - Err = NULL; - break; - } - return Err; + switch (ErrorCode) { + case E_GIF_ERR_OPEN_FAILED: + Err = "Failed to open given file"; + break; + case E_GIF_ERR_WRITE_FAILED: + Err = "Failed to write to given file"; + break; + case E_GIF_ERR_HAS_SCRN_DSCR: + Err = "Screen descriptor has already been set"; + break; + case E_GIF_ERR_HAS_IMAG_DSCR: + Err = "Image descriptor is still active"; + break; + case E_GIF_ERR_NO_COLOR_MAP: + Err = "Neither global nor local color map"; + break; + case E_GIF_ERR_DATA_TOO_BIG: + Err = "Number of pixels bigger than width * height"; + break; + case E_GIF_ERR_NOT_ENOUGH_MEM: + Err = "Failed to allocate required memory"; + break; + case E_GIF_ERR_DISK_IS_FULL: + Err = "Write failed (disk full?)"; + break; + case E_GIF_ERR_CLOSE_FAILED: + Err = "Failed to close given file"; + break; + case E_GIF_ERR_NOT_WRITEABLE: + Err = "Given file was not opened for write"; + break; + case D_GIF_ERR_OPEN_FAILED: + Err = "Failed to open given file"; + break; + case D_GIF_ERR_READ_FAILED: + Err = "Failed to read from given file"; + break; + case D_GIF_ERR_NOT_GIF_FILE: + Err = "Data is not in GIF format"; + break; + case D_GIF_ERR_NO_SCRN_DSCR: + Err = "No screen descriptor detected"; + break; + case D_GIF_ERR_NO_IMAG_DSCR: + Err = "No Image Descriptor detected"; + break; + case D_GIF_ERR_NO_COLOR_MAP: + Err = "Neither global nor local color map"; + break; + case D_GIF_ERR_WRONG_RECORD: + Err = "Wrong record type detected"; + break; + case D_GIF_ERR_DATA_TOO_BIG: + Err = "Number of pixels bigger than width * height"; + break; + case D_GIF_ERR_NOT_ENOUGH_MEM: + Err = "Failed to allocate required memory"; + break; + case D_GIF_ERR_CLOSE_FAILED: + Err = "Failed to close given file"; + break; + case D_GIF_ERR_NOT_READABLE: + Err = "Given file was not opened for read"; + break; + case D_GIF_ERR_IMAGE_DEFECT: + Err = "Image is defective, decoding aborted"; + break; + case D_GIF_ERR_EOF_TOO_SOON: + Err = "Image EOF detected before image complete"; + break; + default: + Err = NULL; + break; + } + return Err; } /* end */ diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h index bd00af64161..eb3cba3135f 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h @@ -26,9 +26,8 @@ gif_hash.h - magfic constants and declarations for GIF LZW -SPDX-License-Identifier: MIT - ******************************************************************************/ +// SPDX-License-Identifier: MIT #ifndef _GIF_HASH_H_ #define _GIF_HASH_H_ @@ -46,7 +45,7 @@ SPDX-License-Identifier: MIT /* The 32 bits of the long are divided into two parts for the key & code: */ /* 1. The code is 12 bits as our compression algorithm is limited to 12bits */ -/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */ +/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */ /* The key is the upper 20 bits. The code is the lower 12. */ #define HT_GET_KEY(l) (l >> 12) #define HT_GET_CODE(l) (l & 0x0FFF) @@ -54,7 +53,7 @@ SPDX-License-Identifier: MIT #define HT_PUT_CODE(l) (l & 0x0FFF) typedef struct GifHashTableType { - uint32_t HTable[HT_SIZE]; + uint32_t HTable[HT_SIZE]; } GifHashTableType; GifHashTableType *_InitHashTable(void); diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h index 74a2e969c0d..5d9c3346090 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h @@ -37,9 +37,9 @@ SPDX-License-Identifier: MIT extern "C" { #endif /* __cplusplus */ -#define GIFLIB_MAJOR 5 -#define GIFLIB_MINOR 2 -#define GIFLIB_RELEASE 2 +#define GIFLIB_MAJOR 6 +#define GIFLIB_MINOR 1 +#define GIFLIB_RELEASE 1 #define GIF_ERROR 0 #define GIF_OK 1 @@ -60,26 +60,26 @@ typedef unsigned int GifPrefixType; typedef int GifWord; typedef struct GifColorType { - GifByteType Red, Green, Blue; + GifByteType Red, Green, Blue; } GifColorType; typedef struct ColorMapObject { - int ColorCount; - int BitsPerPixel; - bool SortFlag; - GifColorType *Colors; /* on malloc(3) heap */ + int ColorCount; + int BitsPerPixel; + bool SortFlag; + GifColorType *Colors; /* on malloc(3) heap */ } ColorMapObject; typedef struct GifImageDesc { - GifWord Left, Top, Width, Height; /* Current image dimensions. */ - bool Interlace; /* Sequential/Interlaced lines. */ - ColorMapObject *ColorMap; /* The local color map */ + GifWord Left, Top, Width, Height; /* Current image dimensions. */ + bool Interlace; /* Sequential/Interlaced lines. */ + ColorMapObject *ColorMap; /* The local color map */ } GifImageDesc; typedef struct ExtensionBlock { - int ByteCount; - GifByteType *Bytes; /* on malloc(3) heap */ - int Function; /* The block function code */ + int ByteCount; + GifByteType *Bytes; /* on malloc(3) heap */ + int Function; /* The block function code */ #define CONTINUE_EXT_FUNC_CODE 0x00 /* continuation subblock */ #define COMMENT_EXT_FUNC_CODE 0xfe /* comment */ #define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */ @@ -88,36 +88,36 @@ typedef struct ExtensionBlock { } ExtensionBlock; typedef struct SavedImage { - GifImageDesc ImageDesc; - GifByteType *RasterBits; /* on malloc(3) heap */ - int ExtensionBlockCount; /* Count of extensions before image */ - ExtensionBlock *ExtensionBlocks; /* Extensions before image */ + GifImageDesc ImageDesc; + GifByteType *RasterBits; /* on malloc(3) heap */ + int ExtensionBlockCount; /* Count of extensions before image */ + ExtensionBlock *ExtensionBlocks; /* Extensions before image */ } SavedImage; typedef struct GifFileType { - GifWord SWidth, SHeight; /* Size of virtual canvas */ - GifWord SColorResolution; /* How many colors can we generate? */ - GifWord SBackGroundColor; /* Background color for virtual canvas */ - GifByteType AspectByte; /* Used to compute pixel aspect ratio */ - ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */ - int ImageCount; /* Number of current image (both APIs) */ - GifImageDesc Image; /* Current image (low-level API) */ - SavedImage *SavedImages; /* Image sequence (high-level API) */ - int ExtensionBlockCount; /* Count extensions past last image */ - ExtensionBlock *ExtensionBlocks; /* Extensions past last image */ - int Error; /* Last error condition reported */ - void *UserData; /* hook to attach user data (TVT) */ - void *Private; /* Don't mess with this! */ + GifWord SWidth, SHeight; /* Size of virtual canvas */ + GifWord SColorResolution; /* How many colors can we generate? */ + GifWord SBackGroundColor; /* Background color for virtual canvas */ + GifByteType AspectByte; /* Used to compute pixel aspect ratio */ + ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */ + int ImageCount; /* Number of current image (both APIs) */ + GifImageDesc Image; /* Current image (low-level API) */ + SavedImage *SavedImages; /* Image sequence (high-level API) */ + int ExtensionBlockCount; /* Count extensions past last image */ + ExtensionBlock *ExtensionBlocks; /* Extensions past last image */ + int Error; /* Last error condition reported */ + void *UserData; /* hook to attach user data (TVT) */ + void *Private; /* Don't mess with this! */ } GifFileType; #define GIF_ASPECT_RATIO(n) ((n) + 15.0 / 64.0) typedef enum { - UNDEFINED_RECORD_TYPE, - SCREEN_DESC_RECORD_TYPE, - IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */ - EXTENSION_RECORD_TYPE, /* Begin with '!' */ - TERMINATE_RECORD_TYPE /* Begin with ';' */ + UNDEFINED_RECORD_TYPE, + SCREEN_DESC_RECORD_TYPE, + IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */ + EXTENSION_RECORD_TYPE, /* Begin with '!' */ + TERMINATE_RECORD_TYPE /* Begin with ';' */ } GifRecordType; /* func type to read gif data from arbitrary sources (TVT) */ @@ -133,14 +133,14 @@ typedef int (*OutputFunc)(GifFileType *, const GifByteType *, int); ******************************************************************************/ typedef struct GraphicsControlBlock { - int DisposalMode; + int DisposalMode; #define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */ #define DISPOSE_DO_NOT 1 /* Leave image in place */ #define DISPOSE_BACKGROUND 2 /* Set area too background color */ #define DISPOSE_PREVIOUS 3 /* Restore to previous content */ - bool UserInputFlag; /* User confirmation required before disposal */ - int DelayTime; /* pre-display delay in 0.01sec units */ - int TransparentColor; /* Palette index for transparency, -1 if none */ + bool UserInputFlag; /* User confirmation required before disposal */ + int DelayTime; /* pre-display delay in 0.01sec units */ + int TransparentColor; /* Palette index for transparency, -1 if none */ #define NO_TRANSPARENT_COLOR -1 } GraphicsControlBlock; @@ -153,21 +153,21 @@ GifFileType *EGifOpenFileName(const char *GifFileName, const bool GifTestExistence, int *Error); GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error); GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error); -int EGifSpew(GifFileType *GifFile); +int EGifSpew(GifFileType *GifFile, int *ErrorCode); const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */ int EGifCloseFile(GifFileType *GifFile, int *ErrorCode); #define E_GIF_SUCCEEDED 0 -#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */ -#define E_GIF_ERR_WRITE_FAILED 2 -#define E_GIF_ERR_HAS_SCRN_DSCR 3 -#define E_GIF_ERR_HAS_IMAG_DSCR 4 -#define E_GIF_ERR_NO_COLOR_MAP 5 -#define E_GIF_ERR_DATA_TOO_BIG 6 -#define E_GIF_ERR_NOT_ENOUGH_MEM 7 -#define E_GIF_ERR_DISK_IS_FULL 8 -#define E_GIF_ERR_CLOSE_FAILED 9 -#define E_GIF_ERR_NOT_WRITEABLE 10 +#define E_GIF_ERR_OPEN_FAILED 201 /* And EGif possible errors. */ +#define E_GIF_ERR_WRITE_FAILED 202 +#define E_GIF_ERR_HAS_SCRN_DSCR 203 +#define E_GIF_ERR_HAS_IMAG_DSCR 204 +#define E_GIF_ERR_NO_COLOR_MAP 205 +#define E_GIF_ERR_DATA_TOO_BIG 206 +#define E_GIF_ERR_NOT_ENOUGH_MEM 207 +#define E_GIF_ERR_DISK_IS_FULL 208 +#define E_GIF_ERR_CLOSE_FAILED 209 +#define E_GIF_ERR_NOT_WRITEABLE 210 /* These are legacy. You probably do not want to call them directly */ int EGifPutScreenDesc(GifFileType *GifFile, const int GifWidth, diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h index f905e0d7b48..079d05898b4 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h @@ -60,30 +60,30 @@ SPDX-License-Identifier: MIT #define IS_WRITEABLE(Private) (Private->FileState & FILE_STATE_WRITE) typedef struct GifFilePrivateType { - GifWord FileState, FileHandle, /* Where all this data goes to! */ - BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */ - ClearCode, /* The CLEAR LZ code. */ - EOFCode, /* The EOF LZ code. */ - RunningCode, /* The next code algorithm can generate. */ - RunningBits, /* The number of bits required to represent - RunningCode. */ - MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. - */ - LastCode, /* The code before the current code. */ - CrntCode, /* Current algorithm code. */ - StackPtr, /* For character stack (see below). */ - CrntShiftState; /* Number of bits in CrntShiftDWord. */ - unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ - unsigned long PixelCount; /* Number of pixels in image. */ - FILE *File; /* File as stream. */ - InputFunc Read; /* function to read gif input (TVT) */ - OutputFunc Write; /* function to write gif output (MRB) */ - GifByteType Buf[256]; /* Compressed input is buffered here. */ - GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ - GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ - GifPrefixType Prefix[LZ_MAX_CODE + 1]; - GifHashTableType *HashTable; - bool gif89; + GifWord FileState, FileHandle, /* Where all this data goes to! */ + BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */ + ClearCode, /* The CLEAR LZ code. */ + EOFCode, /* The EOF LZ code. */ + RunningCode, /* The next code algorithm can generate. */ + RunningBits, /* The number of bits required to represent + RunningCode. */ + MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. + */ + LastCode, /* The code before the current code. */ + CrntCode, /* Current algorithm code. */ + StackPtr, /* For character stack (see below). */ + CrntShiftState; /* Number of bits in CrntShiftDWord. */ + unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */ + unsigned long PixelCount; /* Number of pixels in image. */ + FILE *File; /* File as stream. */ + InputFunc Read; /* function to read gif input (TVT) */ + OutputFunc Write; /* function to write gif output (MRB) */ + GifByteType Buf[256]; /* Compressed input is buffered here. */ + GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */ + GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */ + GifPrefixType Prefix[LZ_MAX_CODE + 1]; + GifHashTableType *HashTable; + bool gif89; } GifFilePrivateType; #ifndef HAVE_REALLOCARRAY diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c b/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c index 5aef3044558..aebf2d7662f 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c @@ -26,9 +26,9 @@ GIF construction tools -SPDX-License-Identifier: MIT - ****************************************************************************/ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: Copyright (C) Eric S. Raymond #include #include @@ -45,14 +45,14 @@ SPDX-License-Identifier: MIT /* return smallest bitfield size n will fit in */ int GifBitSize(int n) { - register int i; + register int i; - for (i = 1; i <= 8; i++) { - if ((1 << i) >= n) { - break; + for (i = 1; i <= 8; i++) { + if ((1 << i) >= n) { + break; + } } - } - return (i); + return (i); } /****************************************************************************** @@ -64,64 +64,64 @@ int GifBitSize(int n) { * ColorMap if that pointer is non-NULL. */ ColorMapObject *GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) { - ColorMapObject *Object; + ColorMapObject *Object; - /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to - * make the user know that or should we automatically round up instead? - */ - if (ColorCount != (1 << GifBitSize(ColorCount))) { - return ((ColorMapObject *)NULL); - } + /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to + * make the user know that or should we automatically round up instead? + */ + if (ColorCount != (1 << GifBitSize(ColorCount))) { + return ((ColorMapObject *)NULL); + } - Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); - if (Object == (ColorMapObject *)NULL) { - return ((ColorMapObject *)NULL); - } + Object = (ColorMapObject *)malloc(sizeof(ColorMapObject)); + if (Object == (ColorMapObject *)NULL) { + return ((ColorMapObject *)NULL); + } - Object->Colors = - (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); - if (Object->Colors == (GifColorType *)NULL) { - free(Object); - return ((ColorMapObject *)NULL); - } + Object->Colors = + (GifColorType *)calloc(ColorCount, sizeof(GifColorType)); + if (Object->Colors == (GifColorType *)NULL) { + free(Object); + return ((ColorMapObject *)NULL); + } - Object->ColorCount = ColorCount; - Object->BitsPerPixel = GifBitSize(ColorCount); - Object->SortFlag = false; + Object->ColorCount = ColorCount; + Object->BitsPerPixel = GifBitSize(ColorCount); + Object->SortFlag = false; - if (ColorMap != NULL) { - memcpy((char *)Object->Colors, (char *)ColorMap, - ColorCount * sizeof(GifColorType)); - } + if (ColorMap != NULL) { + memcpy((char *)Object->Colors, (char *)ColorMap, + ColorCount * sizeof(GifColorType)); + } - return (Object); + return (Object); } /******************************************************************************* Free a color map object *******************************************************************************/ void GifFreeMapObject(ColorMapObject *Object) { - if (Object != NULL) { - (void)free(Object->Colors); - (void)free(Object); - } + if (Object != NULL) { + (void)free(Object->Colors); + (void)free(Object); + } } #ifdef DEBUG void DumpColorMap(ColorMapObject *Object, FILE *fp) { - if (Object != NULL) { - int i, j, Len = Object->ColorCount; + if (Object != NULL) { + int i, j, Len = Object->ColorCount; - for (i = 0; i < Len; i += 4) { - for (j = 0; j < 4 && j < Len; j++) { - (void)fprintf(fp, "%3d: %02x %02x %02x ", - i + j, Object->Colors[i + j].Red, - Object->Colors[i + j].Green, - Object->Colors[i + j].Blue); - } - (void)fprintf(fp, "\n"); + for (i = 0; i < Len; i += 4) { + for (j = 0; j < 4 && j < Len; j++) { + (void)fprintf(fp, "%3d: %02x %02x %02x ", + i + j, Object->Colors[i + j].Red, + Object->Colors[i + j].Green, + Object->Colors[i + j].Blue); + } + (void)fprintf(fp, "\n"); + } } - } } #endif /* DEBUG */ @@ -135,112 +135,112 @@ void DumpColorMap(ColorMapObject *Object, FILE *fp) { ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1, const ColorMapObject *ColorIn2, GifPixelType ColorTransIn2[]) { - int i, j, CrntSlot, RoundUpTo, NewGifBitSize; - ColorMapObject *ColorUnion; - - /* - * We don't worry about duplicates within either color map; if - * the caller wants to resolve those, he can perform unions - * with an empty color map. - */ - - /* Allocate table which will hold the result for sure. */ - ColorUnion = GifMakeMapObject( - MAX(ColorIn1->ColorCount, ColorIn2->ColorCount) * 2, NULL); - - if (ColorUnion == NULL) { - return (NULL); - } - - /* - * Copy ColorIn1 to ColorUnion. - */ - for (i = 0; i < ColorIn1->ColorCount; i++) { - ColorUnion->Colors[i] = ColorIn1->Colors[i]; - } - CrntSlot = ColorIn1->ColorCount; - - /* - * Potentially obnoxious hack: - * - * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end - * of table 1. This is very useful if your display is limited to - * 16 colors. - */ - while (ColorIn1->Colors[CrntSlot - 1].Red == 0 && - ColorIn1->Colors[CrntSlot - 1].Green == 0 && - ColorIn1->Colors[CrntSlot - 1].Blue == 0) { - CrntSlot--; - } - - /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ - for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { - /* Let's see if this color already exists: */ - for (j = 0; j < ColorIn1->ColorCount; j++) { - if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], - sizeof(GifColorType)) == 0) { - break; - } - } - - if (j < ColorIn1->ColorCount) { - ColorTransIn2[i] = j; /* color exists in Color1 */ - } else { - /* Color is new - copy it to a new slot: */ - ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; - ColorTransIn2[i] = CrntSlot++; - } - } - - if (CrntSlot > 256) { - GifFreeMapObject(ColorUnion); - return ((ColorMapObject *)NULL); - } - - NewGifBitSize = GifBitSize(CrntSlot); - RoundUpTo = (1 << NewGifBitSize); - - if (RoundUpTo != ColorUnion->ColorCount) { - register GifColorType *Map = ColorUnion->Colors; + int i, j, CrntSlot, RoundUpTo, NewGifBitSize; + ColorMapObject *ColorUnion; /* - * Zero out slots up to next power of 2. - * We know these slots exist because of the way ColorUnion's - * start dimension was computed. + * We don't worry about duplicates within either color map; if + * the caller wants to resolve those, he can perform unions + * with an empty color map. */ - for (j = CrntSlot; j < RoundUpTo; j++) { - Map[j].Red = Map[j].Green = Map[j].Blue = 0; + + /* Allocate table which will hold the result for sure. */ + ColorUnion = GifMakeMapObject( + MAX(ColorIn1->ColorCount, ColorIn2->ColorCount) * 2, NULL); + + if (ColorUnion == NULL) { + return (NULL); } - /* perhaps we can shrink the map? */ - if (RoundUpTo < ColorUnion->ColorCount) { - GifColorType *new_map = (GifColorType *)reallocarray( - Map, RoundUpTo, sizeof(GifColorType)); - if (new_map == NULL) { + /* + * Copy ColorIn1 to ColorUnion. + */ + for (i = 0; i < ColorIn1->ColorCount; i++) { + ColorUnion->Colors[i] = ColorIn1->Colors[i]; + } + CrntSlot = ColorIn1->ColorCount; + + /* + * Potentially obnoxious hack: + * + * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end + * of table 1. This is very useful if your display is limited to + * 16 colors. + */ + while (ColorIn1->Colors[CrntSlot - 1].Red == 0 && + ColorIn1->Colors[CrntSlot - 1].Green == 0 && + ColorIn1->Colors[CrntSlot - 1].Blue == 0) { + CrntSlot--; + } + + /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */ + for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) { + /* Let's see if this color already exists: */ + for (j = 0; j < ColorIn1->ColorCount; j++) { + if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], + sizeof(GifColorType)) == 0) { + break; + } + } + + if (j < ColorIn1->ColorCount) { + ColorTransIn2[i] = j; /* color exists in Color1 */ + } else { + /* Color is new - copy it to a new slot: */ + ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i]; + ColorTransIn2[i] = CrntSlot++; + } + } + + if (CrntSlot > 256) { GifFreeMapObject(ColorUnion); return ((ColorMapObject *)NULL); - } - ColorUnion->Colors = new_map; } - } - ColorUnion->ColorCount = RoundUpTo; - ColorUnion->BitsPerPixel = NewGifBitSize; + NewGifBitSize = GifBitSize(CrntSlot); + RoundUpTo = (1 << NewGifBitSize); - return (ColorUnion); + if (RoundUpTo != ColorUnion->ColorCount) { + register GifColorType *Map = ColorUnion->Colors; + + /* + * Zero out slots up to next power of 2. + * We know these slots exist because of the way ColorUnion's + * start dimension was computed. + */ + for (j = CrntSlot; j < RoundUpTo; j++) { + Map[j].Red = Map[j].Green = Map[j].Blue = 0; + } + + /* perhaps we can shrink the map? */ + if (RoundUpTo < ColorUnion->ColorCount) { + GifColorType *new_map = (GifColorType *)reallocarray( + Map, RoundUpTo, sizeof(GifColorType)); + if (new_map == NULL) { + GifFreeMapObject(ColorUnion); + return ((ColorMapObject *)NULL); + } + ColorUnion->Colors = new_map; + } + } + + ColorUnion->ColorCount = RoundUpTo; + ColorUnion->BitsPerPixel = NewGifBitSize; + + return (ColorUnion); } /******************************************************************************* Apply a given color translation to the raster bits of an image *******************************************************************************/ void GifApplyTranslation(SavedImage *Image, const GifPixelType Translation[]) { - register int i; - register int RasterSize = - Image->ImageDesc.Height * Image->ImageDesc.Width; + register int i; + register int RasterSize = + Image->ImageDesc.Height * Image->ImageDesc.Width; - for (i = 0; i < RasterSize; i++) { - Image->RasterBits[i] = Translation[Image->RasterBits[i]]; - } + for (i = 0; i < RasterSize; i++) { + Image->RasterBits[i] = Translation[Image->RasterBits[i]]; + } } /****************************************************************************** @@ -249,56 +249,56 @@ void GifApplyTranslation(SavedImage *Image, const GifPixelType Translation[]) { int GifAddExtensionBlock(int *ExtensionBlockCount, ExtensionBlock **ExtensionBlocks, int Function, unsigned int Len, unsigned char ExtData[]) { - ExtensionBlock *ep; + ExtensionBlock *ep; - if (*ExtensionBlocks == NULL) { - *ExtensionBlocks = - (ExtensionBlock *)malloc(sizeof(ExtensionBlock)); - } else { - ExtensionBlock *ep_new = (ExtensionBlock *)reallocarray( - *ExtensionBlocks, (*ExtensionBlockCount + 1), - sizeof(ExtensionBlock)); - if (ep_new == NULL) { - return (GIF_ERROR); + if (*ExtensionBlocks == NULL) { + *ExtensionBlocks = + (ExtensionBlock *)malloc(sizeof(ExtensionBlock)); + } else { + ExtensionBlock *ep_new = (ExtensionBlock *)reallocarray( + *ExtensionBlocks, (*ExtensionBlockCount + 1), + sizeof(ExtensionBlock)); + if (ep_new == NULL) { + return (GIF_ERROR); + } + *ExtensionBlocks = ep_new; } - *ExtensionBlocks = ep_new; - } - if (*ExtensionBlocks == NULL) { - return (GIF_ERROR); - } + if (*ExtensionBlocks == NULL) { + return (GIF_ERROR); + } - ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; + ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++]; - ep->Function = Function; - ep->ByteCount = Len; - ep->Bytes = (GifByteType *)malloc(ep->ByteCount); - if (ep->Bytes == NULL) { - return (GIF_ERROR); - } + ep->Function = Function; + ep->ByteCount = Len; + ep->Bytes = (GifByteType *)malloc(ep->ByteCount); + if (ep->Bytes == NULL) { + return (GIF_ERROR); + } - if (ExtData != NULL) { - memcpy(ep->Bytes, ExtData, Len); - } + if (ExtData != NULL) { + memcpy(ep->Bytes, ExtData, Len); + } - return (GIF_OK); + return (GIF_OK); } void GifFreeExtensions(int *ExtensionBlockCount, ExtensionBlock **ExtensionBlocks) { - ExtensionBlock *ep; + ExtensionBlock *ep; - if (*ExtensionBlocks == NULL) { - return; - } + if (*ExtensionBlocks == NULL) { + return; + } - for (ep = *ExtensionBlocks; - ep < (*ExtensionBlocks + *ExtensionBlockCount); ep++) { - (void)free((char *)ep->Bytes); - } - (void)free((char *)*ExtensionBlocks); - *ExtensionBlocks = NULL; - *ExtensionBlockCount = 0; + for (ep = *ExtensionBlocks; + ep < (*ExtensionBlocks + *ExtensionBlockCount); ep++) { + (void)free((char *)ep->Bytes); + } + (void)free((char *)*ExtensionBlocks); + *ExtensionBlocks = NULL; + *ExtensionBlockCount = 0; } /****************************************************************************** @@ -309,37 +309,37 @@ void GifFreeExtensions(int *ExtensionBlockCount, * Frees the last image in the GifFile->SavedImages array */ void FreeLastSavedImage(GifFileType *GifFile) { - SavedImage *sp; + SavedImage *sp; - if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { - return; - } + if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { + return; + } - /* Remove one SavedImage from the GifFile */ - GifFile->ImageCount--; - sp = &GifFile->SavedImages[GifFile->ImageCount]; + /* Remove one SavedImage from the GifFile */ + GifFile->ImageCount--; + sp = &GifFile->SavedImages[GifFile->ImageCount]; - /* Deallocate its Colormap */ - if (sp->ImageDesc.ColorMap != NULL) { - GifFreeMapObject(sp->ImageDesc.ColorMap); - sp->ImageDesc.ColorMap = NULL; - } + /* Deallocate its Colormap */ + if (sp->ImageDesc.ColorMap != NULL) { + GifFreeMapObject(sp->ImageDesc.ColorMap); + sp->ImageDesc.ColorMap = NULL; + } - /* Deallocate the image data */ - if (sp->RasterBits != NULL) { - free((char *)sp->RasterBits); - } + /* Deallocate the image data */ + if (sp->RasterBits != NULL) { + free((char *)sp->RasterBits); + } - /* Deallocate any extensions */ - GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); + /* Deallocate any extensions */ + GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks); - /*** FIXME: We could realloc the GifFile->SavedImages structure but is - * there a point to it? Saves some memory but we'd have to do it every - * time. If this is used in GifFreeSavedImages then it would be - * inefficient (The whole array is going to be deallocated.) If we just - * use it when we want to free the last Image it's convenient to do it - * here. - */ + /*** FIXME: We could realloc the GifFile->SavedImages structure but is + * there a point to it? Saves some memory but we'd have to do it every + * time. If this is used in GifFreeSavedImages then it would be + * inefficient (The whole array is going to be deallocated.) If we just + * use it when we want to free the last Image it's convenient to do it + * here. + */ } /* @@ -347,103 +347,121 @@ void FreeLastSavedImage(GifFileType *GifFile) { */ SavedImage *GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) { - // cppcheck-suppress ctunullpointer - if (GifFile->SavedImages == NULL) { - GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); - } else { - SavedImage *newSavedImages = (SavedImage *)reallocarray( - GifFile->SavedImages, (GifFile->ImageCount + 1), - sizeof(SavedImage)); - if (newSavedImages == NULL) { - return ((SavedImage *)NULL); - } - GifFile->SavedImages = newSavedImages; - } - if (GifFile->SavedImages == NULL) { - return ((SavedImage *)NULL); - } else { - SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; - - if (CopyFrom != NULL) { - memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); - - /* - * Make our own allocated copies of the heap fields in - * the copied record. This guards against potential - * aliasing problems. - */ - - /* first, the local color map */ - if (CopyFrom->ImageDesc.ColorMap != NULL) { - sp->ImageDesc.ColorMap = GifMakeMapObject( - CopyFrom->ImageDesc.ColorMap->ColorCount, - CopyFrom->ImageDesc.ColorMap->Colors); - if (sp->ImageDesc.ColorMap == NULL) { - FreeLastSavedImage(GifFile); - return (SavedImage *)(NULL); - } - } - - /* next, the raster */ - sp->RasterBits = (unsigned char *)reallocarray( - NULL, - (CopyFrom->ImageDesc.Height * - CopyFrom->ImageDesc.Width), - sizeof(GifPixelType)); - if (sp->RasterBits == NULL) { - FreeLastSavedImage(GifFile); - return (SavedImage *)(NULL); - } - memcpy(sp->RasterBits, CopyFrom->RasterBits, - sizeof(GifPixelType) * - CopyFrom->ImageDesc.Height * - CopyFrom->ImageDesc.Width); - - /* finally, the extension blocks */ - if (CopyFrom->ExtensionBlocks != NULL) { - sp->ExtensionBlocks = - (ExtensionBlock *)reallocarray( - NULL, CopyFrom->ExtensionBlockCount, - sizeof(ExtensionBlock)); - if (sp->ExtensionBlocks == NULL) { - FreeLastSavedImage(GifFile); - return (SavedImage *)(NULL); - } - memcpy(sp->ExtensionBlocks, - CopyFrom->ExtensionBlocks, - sizeof(ExtensionBlock) * - CopyFrom->ExtensionBlockCount); - } + // cppcheck-suppress ctunullpointer + if (GifFile->SavedImages == NULL) { + GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage)); } else { - memset((char *)sp, '\0', sizeof(SavedImage)); + SavedImage *newSavedImages = (SavedImage *)reallocarray( + GifFile->SavedImages, (GifFile->ImageCount + 1), + sizeof(SavedImage)); + if (newSavedImages == NULL) { + return ((SavedImage *)NULL); + } + GifFile->SavedImages = newSavedImages; } + if (GifFile->SavedImages == NULL) { + return ((SavedImage *)NULL); + } else { + SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; - return (sp); - } + if (CopyFrom != NULL) { + memcpy((char *)sp, CopyFrom, sizeof(SavedImage)); + + /* + * Make our own allocated copies of the heap fields in + * the copied record. This guards against potential + * aliasing problems. + */ + + /* first, the local color map */ + if (CopyFrom->ImageDesc.ColorMap != NULL) { + sp->ImageDesc.ColorMap = GifMakeMapObject( + CopyFrom->ImageDesc.ColorMap->ColorCount, + CopyFrom->ImageDesc.ColorMap->Colors); + if (sp->ImageDesc.ColorMap == NULL) { + FreeLastSavedImage(GifFile); + return (SavedImage *)(NULL); + } + } + + /* next, the raster */ + sp->RasterBits = (unsigned char *)reallocarray( + NULL, + (CopyFrom->ImageDesc.Height * + CopyFrom->ImageDesc.Width), + sizeof(GifPixelType)); + if (sp->RasterBits == NULL) { + FreeLastSavedImage(GifFile); + return (SavedImage *)(NULL); + } + memcpy(sp->RasterBits, CopyFrom->RasterBits, + sizeof(GifPixelType) * + CopyFrom->ImageDesc.Height * + CopyFrom->ImageDesc.Width); + + /* finally, the extension blocks */ + if (CopyFrom->ExtensionBlocks != NULL) { + int k; + sp->ExtensionBlocks = + (ExtensionBlock *)calloc( + CopyFrom->ExtensionBlockCount, + sizeof(ExtensionBlock)); + if (sp->ExtensionBlocks == NULL) { + FreeLastSavedImage(GifFile); + return (SavedImage *)(NULL); + } + for (k = 0; k < CopyFrom->ExtensionBlockCount; + k++) { + ExtensionBlock *dst = + &sp->ExtensionBlocks[k]; + ExtensionBlock *src = + &CopyFrom->ExtensionBlocks[k]; + dst->Function = src->Function; + dst->ByteCount = src->ByteCount; + if (src->ByteCount > 0) { + dst->Bytes = + (GifByteType *)malloc( + src->ByteCount); + if (dst->Bytes == NULL) { + FreeLastSavedImage( + GifFile); + return (SavedImage *)(NULL); + } + memcpy(dst->Bytes, src->Bytes, + src->ByteCount); + } + } + } + } else { + memset((char *)sp, '\0', sizeof(SavedImage)); + } + + return (sp); + } } void GifFreeSavedImages(GifFileType *GifFile) { - SavedImage *sp; + SavedImage *sp; - if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { - return; - } - for (sp = GifFile->SavedImages; - sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { - if (sp->ImageDesc.ColorMap != NULL) { - GifFreeMapObject(sp->ImageDesc.ColorMap); - sp->ImageDesc.ColorMap = NULL; + if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) { + return; } + for (sp = GifFile->SavedImages; + sp < GifFile->SavedImages + GifFile->ImageCount; sp++) { + if (sp->ImageDesc.ColorMap != NULL) { + GifFreeMapObject(sp->ImageDesc.ColorMap); + sp->ImageDesc.ColorMap = NULL; + } - if (sp->RasterBits != NULL) { - free((char *)sp->RasterBits); + if (sp->RasterBits != NULL) { + free((char *)sp->RasterBits); + } + + GifFreeExtensions(&sp->ExtensionBlockCount, + &sp->ExtensionBlocks); } - - GifFreeExtensions(&sp->ExtensionBlockCount, - &sp->ExtensionBlocks); - } - free((char *)GifFile->SavedImages); - GifFile->SavedImages = NULL; + free((char *)GifFile->SavedImages); + GifFile->SavedImages = NULL; } /* end */ diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c b/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c index 7420af674c5..57504fceaa9 100644 --- a/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c +++ b/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c @@ -22,9 +22,8 @@ * questions. */ -/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */ /* - * Copyright (c) 2008 Otto Moerbeek + * SPDX-FileCopyrightText: Copyright (C) 2008 Otto Moerbeek * SPDX-License-Identifier: MIT */ @@ -44,55 +43,55 @@ #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) void *openbsd_reallocarray(void *optr, size_t nmemb, size_t size) { - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) { - errno = ENOMEM; - return NULL; - } - /* - * Head off variations in realloc behavior on different - * platforms (reported by MarkR ) - * - * The behaviour of reallocarray is implementation-defined if - * nmemb or size is zero. It can return NULL or non-NULL - * depending on the platform. - * https://www.securecoding.cert.org/confluence/display/c/MEM04-C.Beware+of+zero-lengthallocations - * - * Here are some extracts from realloc man pages on different platforms. - * - * void realloc( void memblock, size_t size ); - * - * Windows: - * - * If there is not enough available memory to expand the block - * to the given size, the original block is left unchanged, - * and NULL is returned. If size is zero, then the block - * pointed to by memblock is freed; the return value is NULL, - * and memblock is left pointing at a freed block. - * - * OpenBSD: - * - * If size or nmemb is equal to 0, a unique pointer to an - * access protected, zero sized object is returned. Access via - * this pointer will generate a SIGSEGV exception. - * - * Linux: - * - * If size was equal to 0, either NULL or a pointer suitable - * to be passed to free() is returned. - * - * OS X: - * - * If size is zero and ptr is not NULL, a new, minimum sized - * object is allocated and the original object is freed. - * - * It looks like images with zero width or height can trigger - * this, and fuzzing behaviour will differ by platform, so - * fuzzing on one platform may not detect zero-size allocation - * problems on other platforms. - */ - if (size == 0 || nmemb == 0) { - return NULL; - } - return realloc(optr, size * nmemb); + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + /* + * Head off variations in realloc behavior on different + * platforms (reported by MarkR ) + * + * The behaviour of reallocarray is implementation-defined if + * nmemb or size is zero. It can return NULL or non-NULL + * depending on the platform. + * https://www.securecoding.cert.org/confluence/display/c/MEM04-C.Beware+of+zero-lengthallocations + * + * Here are some extracts from realloc man pages on different platforms. + * + * void realloc( void memblock, size_t size ); + * + * Windows: + * + * If there is not enough available memory to expand the block + * to the given size, the original block is left unchanged, + * and NULL is returned. If size is zero, then the block + * pointed to by memblock is freed; the return value is NULL, + * and memblock is left pointing at a freed block. + * + * OpenBSD: + * + * If size or nmemb is equal to 0, a unique pointer to an + * access protected, zero sized object is returned. Access via + * this pointer will generate a SIGSEGV exception. + * + * Linux: + * + * If size was equal to 0, either NULL or a pointer suitable + * to be passed to free() is returned. + * + * OS X: + * + * If size is zero and ptr is not NULL, a new, minimum sized + * object is allocated and the original object is freed. + * + * It looks like images with zero width or height can trigger + * this, and fuzzing behaviour will differ by platform, so + * fuzzing on one platform may not detect zero-size allocation + * problems on other platforms. + */ + if (size == 0 || nmemb == 0) { + return NULL; + } + return realloc(optr, size * nmemb); } From 58bf76adfd93303bdd78862ae3677b514754d34d Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Wed, 11 Mar 2026 02:41:36 +0000 Subject: [PATCH 161/170] 8379464: Enable missing stack walking test via jtreg requires for RISC-V Reviewed-by: fyang --- .../jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java b/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java index a964a61003a..1e29afe5ff8 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java @@ -33,7 +33,7 @@ import java.util.List; * @test StackWalkNativeToJava * @bug 8316309 * @summary Check that walking the stack works fine when going from C++ frame to Java frame. - * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="riscv64" * @requires os.family != "windows" * @requires vm.flagless * @library /test/lib From 20ae5279cb458733de07b5c1411c67ae7998fba4 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 11 Mar 2026 04:52:26 +0000 Subject: [PATCH 162/170] 8379477: Tests in test/jdk/com/sun/net/httpserver/ may need to use othervm Reviewed-by: vyazici --- .../sun/net/httpserver/TaskRejectedTest.java | 32 ++++++++------ test/jdk/com/sun/net/httpserver/Test13.java | 44 +++++++++++-------- test/jdk/com/sun/net/httpserver/Test7a.java | 27 +++++------- test/jdk/com/sun/net/httpserver/Test8a.java | 26 +++++------ .../com/sun/net/httpserver/TestLogging.java | 41 ++++++++++------- .../com/sun/net/httpserver/bugs/B6886436.java | 36 ++++++++------- .../com/sun/net/httpserver/bugs/B8211420.java | 32 ++++++++------ .../httpserver/bugs/ExceptionKeepAlive.java | 40 +++++++++-------- .../bugs/FixedLengthInputStream.java | 43 +++++++++--------- .../bugs/HandlerConnectionClose.java | 44 ++++++++++--------- .../net/httpserver/bugs/HeadKeepAlive.java | 40 +++++++++-------- .../httpserver/bugs/TruncatedRequestBody.java | 32 +++++++++----- .../bugs/ZeroLengthOutputStream.java | 41 +++++++++-------- 13 files changed, 257 insertions(+), 221 deletions(-) diff --git a/test/jdk/com/sun/net/httpserver/TaskRejectedTest.java b/test/jdk/com/sun/net/httpserver/TaskRejectedTest.java index 6b6d53fd3a3..109d28627dc 100644 --- a/test/jdk/com/sun/net/httpserver/TaskRejectedTest.java +++ b/test/jdk/com/sun/net/httpserver/TaskRejectedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,6 @@ * questions. */ -/** - * @test - * @bug 8169358 - * @summary HttpServer does not close client connection when RejectedExecutionException occurs. - */ import com.sun.net.httpserver.HttpServer; @@ -46,6 +41,14 @@ import java.util.logging.Level; import java.util.logging.Logger; import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; +/* + * @test + * @bug 8169358 + * @summary HttpServer does not close client connection when RejectedExecutionException occurs. + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + */ public class TaskRejectedTest { private static final int BACKLOG = 0; @@ -54,6 +57,15 @@ public class TaskRejectedTest { private static final int TIMEOUT = 10000; // 10 sec + private static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); + + private static void setupLogging() { + final Handler consoleHandler = new ConsoleHandler(); + consoleHandler.setLevel(Level.FINEST); + logger.setLevel(Level.FINEST); + logger.addHandler(consoleHandler); + } + private static void runClient(InetSocketAddress listenAddr) throws MalformedURLException, IOException { URL url = new URL("http", listenAddr.getHostString(), @@ -75,13 +87,7 @@ public class TaskRejectedTest { } public static void main(String[] args) throws Exception { - Logger logger = Logger.getLogger( - HttpServer.class.getPackage().getName()); - Handler consoleHandler = new ConsoleHandler(); - consoleHandler.setLevel(Level.FINEST); - logger.setLevel(Level.FINEST); - logger.addHandler(consoleHandler); - + setupLogging(); // merely for debugging Executor executor = Executors.newSingleThreadExecutor(r -> { throw new RejectedExecutionException("test"); }); diff --git a/test/jdk/com/sun/net/httpserver/Test13.java b/test/jdk/com/sun/net/httpserver/Test13.java index 0401dbce5a8..503b9e4430c 100644 --- a/test/jdk/com/sun/net/httpserver/Test13.java +++ b/test/jdk/com/sun/net/httpserver/Test13.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,19 +21,6 @@ * questions. */ -/* - * @test - * @bug 6270015 - * @library /test/lib - * @build jdk.test.lib.Asserts - * jdk.test.lib.Utils - * jdk.test.lib.net.SimpleSSLContext - * jdk.test.lib.net.URIBuilder - * @run main/othervm Test13 - * @run main/othervm -Djava.net.preferIPv6Addresses=true Test13 - * @summary Light weight HTTP server - */ - import com.sun.net.httpserver.*; import java.nio.file.Files; @@ -54,6 +41,20 @@ import static jdk.test.lib.Utils.createTempFileOfSize; * - same as Test12, but with 64 threads */ +/* + * @test + * @bug 6270015 + * @summary Light weight HTTP server + * @library /test/lib + * @build jdk.test.lib.Asserts + * jdk.test.lib.Utils + * jdk.test.lib.net.SimpleSSLContext + * jdk.test.lib.net.URIBuilder + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + * @run main/othervm -Djava.net.preferIPv6Addresses=true ${test.main.class} + */ public class Test13 extends Test { private static final String TEMP_FILE_PREFIX = @@ -61,20 +62,25 @@ public class Test13 extends Test { private static final SSLContext ctx = SimpleSSLContext.findSSLContext(); + private static final Logger logger = Logger.getLogger ("com.sun.net.httpserver"); + final static int NUM = 32; // was 32 static boolean fail = false; + private static void setupLogging() { + final Handler handler = new ConsoleHandler(); + handler.setLevel(Level.ALL); + logger.setLevel(Level.ALL); + logger.addHandler(handler); + } + public static void main (String[] args) throws Exception { HttpServer s1 = null; HttpsServer s2 = null; ExecutorService executor=null; Path filePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 23); - Logger l = Logger.getLogger ("com.sun.net.httpserver"); - Handler ha = new ConsoleHandler(); - ha.setLevel(Level.ALL); - l.setLevel(Level.ALL); - l.addHandler(ha); + setupLogging(); // merely for debugging InetAddress loopback = InetAddress.getLoopbackAddress(); try { System.out.print ("Test13: "); diff --git a/test/jdk/com/sun/net/httpserver/Test7a.java b/test/jdk/com/sun/net/httpserver/Test7a.java index 8bda4ae8348..832238b2b47 100644 --- a/test/jdk/com/sun/net/httpserver/Test7a.java +++ b/test/jdk/com/sun/net/httpserver/Test7a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,16 +21,6 @@ * questions. */ -/** - * @test - * @bug 6270015 - * @library /test/lib - * @build jdk.test.lib.net.SimpleSSLContext jdk.test.lib.net.URIBuilder - * @run main/othervm Test7a - * @run main/othervm -Djava.net.preferIPv6Addresses=true Test7a - * @summary Light weight HTTP server - */ - import com.sun.net.httpserver.*; import java.util.concurrent.*; @@ -44,15 +34,18 @@ import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; /** * Test POST large file via chunked encoding (large chunks) */ - +/* + * @test + * @bug 6270015 + * @summary Light weight HTTP server + * @library /test/lib + * @build jdk.test.lib.net.SimpleSSLContext jdk.test.lib.net.URIBuilder + * @run main/othervm ${test.main.class} + * @run main/othervm -Djava.net.preferIPv6Addresses=true ${test.main.class} + */ public class Test7a extends Test { public static void main (String[] args) throws Exception { - //Logger log = Logger.getLogger ("com.sun.net.httpserver"); - //log.setLevel (Level.FINE); - //ConsoleHandler h = new ConsoleHandler(); - //h.setLevel (Level.ALL); - //log.addHandler (h); Handler handler = new Handler(); InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress addr = new InetSocketAddress(loopback, 0); diff --git a/test/jdk/com/sun/net/httpserver/Test8a.java b/test/jdk/com/sun/net/httpserver/Test8a.java index 67f9c93172a..9d1525352cf 100644 --- a/test/jdk/com/sun/net/httpserver/Test8a.java +++ b/test/jdk/com/sun/net/httpserver/Test8a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,6 @@ * questions. */ -/** - * @test - * @bug 6270015 - * @library /test/lib - * @build jdk.test.lib.net.SimpleSSLContext jdk.test.lib.net.URIBuilder - * @run main/othervm Test8a - * @run main/othervm -Djava.net.preferIPv6Addresses=true Test8a - * @summary Light weight HTTP server - */ import com.sun.net.httpserver.*; @@ -43,15 +34,18 @@ import jdk.test.lib.net.URIBuilder; /** * Test POST large file via fixed len encoding */ - +/* + * @test + * @bug 6270015 + * @summary Light weight HTTP server + * @library /test/lib + * @build jdk.test.lib.net.SimpleSSLContext jdk.test.lib.net.URIBuilder + * @run main/othervm ${test.main.class} + * @run main/othervm -Djava.net.preferIPv6Addresses=true ${test.main.class} + */ public class Test8a extends Test { public static void main (String[] args) throws Exception { - //Logger log = Logger.getLogger ("com.sun.net.httpserver"); - //ConsoleHandler h = new ConsoleHandler(); - //h.setLevel (Level.INFO); - //log.addHandler (h); - //log.setLevel (Level.INFO); HttpsServer server = null; ExecutorService executor = null; try { diff --git a/test/jdk/com/sun/net/httpserver/TestLogging.java b/test/jdk/com/sun/net/httpserver/TestLogging.java index 8f4fbddcd42..3f201f90dd2 100644 --- a/test/jdk/com/sun/net/httpserver/TestLogging.java +++ b/test/jdk/com/sun/net/httpserver/TestLogging.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2026, Oracle and/or its affiliates. All rights reserved. * 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,16 +21,6 @@ * questions. */ -/* - * @test - * @bug 6422914 - * @library /test/lib - * @build jdk.test.lib.Utils - * jdk.test.lib.net.URIBuilder - * @summary change httpserver exception printouts - * @run main TestLogging - * @run main/othervm -Djava.net.preferIPv6Addresses=true TestLogging - */ import com.sun.net.httpserver.*; @@ -45,27 +35,44 @@ import jdk.test.lib.net.URIBuilder; import static jdk.test.lib.Utils.createTempFileOfSize; +/* + * @test + * @bug 6422914 + * @summary change httpserver exception printouts + * @library /test/lib + * @build jdk.test.lib.Utils + * jdk.test.lib.net.URIBuilder + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + * @run main/othervm -Djava.net.preferIPv6Addresses=true ${test.main.class} + */ public class TestLogging extends Test { private static final String TEMP_FILE_PREFIX = HttpServer.class.getPackageName() + '-' + TestLogging.class.getSimpleName() + '-'; + private static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); + + private static void setupLogging() { + logger.setLevel(Level.ALL); + final Handler handler = new ConsoleHandler(); + handler.setLevel(Level.ALL); + logger.addHandler(handler); + } + public static void main (String[] args) throws Exception { HttpServer s1 = null; ExecutorService executor=null; Path filePath = createTempFileOfSize(TEMP_FILE_PREFIX, null, 0xBEEF); try { System.out.print ("Test9: "); + setupLogging(); String root = filePath.getParent().toString(); InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress addr = new InetSocketAddress(loopback, 0); - Logger logger = Logger.getLogger ("com.sun.net.httpserver"); - logger.setLevel (Level.ALL); - Handler h1 = new ConsoleHandler (); - h1.setLevel (Level.ALL); - logger.addHandler (h1); s1 = HttpServer.create (addr, 0); - logger.info (root); + logger.info(root); HttpHandler h = new FileServerHandler (root); HttpContext c1 = s1.createContext ("/", h); executor = Executors.newCachedThreadPool(); diff --git a/test/jdk/com/sun/net/httpserver/bugs/B6886436.java b/test/jdk/com/sun/net/httpserver/bugs/B6886436.java index 5081a81c4c1..c52bbcbdfce 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/B6886436.java +++ b/test/jdk/com/sun/net/httpserver/bugs/B6886436.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,6 @@ * questions. */ -/** - * @test - * @bug 6886436 - * @summary HttpServer should not send a body with 204 response. - * @library /test/lib - * @run main B6886436 - * @run main/othervm -Djava.net.preferIPv6Addresses=true B6886436 - */ - import com.sun.net.httpserver.*; import java.util.*; @@ -40,14 +31,29 @@ import java.net.*; import jdk.test.lib.net.URIBuilder; import static com.sun.net.httpserver.HttpExchange.RSPBODY_CHUNKED; +/* + * @test + * @bug 6886436 + * @summary HttpServer should not send a body with 204 response. + * @library /test/lib + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + * @run main/othervm -Djava.net.preferIPv6Addresses=true ${test.main.class} + */ public class B6886436 { + private static final Logger logger = Logger.getLogger ("com.sun.net.httpserver"); + + private static void setupLogging() { + final ConsoleHandler c = new ConsoleHandler(); + c.setLevel(Level.WARNING); + logger.addHandler(c); + logger.setLevel(Level.WARNING); + } + public static void main (String[] args) throws Exception { - Logger logger = Logger.getLogger ("com.sun.net.httpserver"); - ConsoleHandler c = new ConsoleHandler(); - c.setLevel (Level.WARNING); - logger.addHandler (c); - logger.setLevel (Level.WARNING); + setupLogging(); // merely for debugging Handler handler = new Handler(); InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress addr = new InetSocketAddress (loopback, 0); diff --git a/test/jdk/com/sun/net/httpserver/bugs/B8211420.java b/test/jdk/com/sun/net/httpserver/bugs/B8211420.java index 297aed43bec..d7257ddc755 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/B8211420.java +++ b/test/jdk/com/sun/net/httpserver/bugs/B8211420.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,6 @@ * questions. */ -/** - * @test - * @bug 8211420 - * @library /test/lib - * @run main/othervm B8211420 - * @run main/othervm -Djava.net.preferIPv6Addresses=true B8211420 - * @summary - */ - import com.sun.net.httpserver.*; import java.util.*; @@ -41,14 +32,29 @@ import java.net.*; import jdk.test.lib.net.URIBuilder; import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; +/* + * @test + * @bug 8211420 + * @library /test/lib + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + * @run main/othervm -Djava.net.preferIPv6Addresses=true ${test.main.class} + * @summary + */ public class B8211420 { - public static void main(String[] args) throws Exception { - Logger logger = Logger.getLogger("com.sun.net.httpserver"); - ConsoleHandler c = new ConsoleHandler(); + private static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); + + private static void setupLogging() { + final ConsoleHandler c = new ConsoleHandler(); c.setLevel(Level.WARNING); logger.addHandler(c); logger.setLevel(Level.WARNING); + } + + public static void main(String[] args) throws Exception { + setupLogging(); // merely for debugging Handler handler = new Handler(); InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress addr = new InetSocketAddress(loopback, 0); diff --git a/test/jdk/com/sun/net/httpserver/bugs/ExceptionKeepAlive.java b/test/jdk/com/sun/net/httpserver/bugs/ExceptionKeepAlive.java index 865e3b7509d..eba6aa67a8f 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/ExceptionKeepAlive.java +++ b/test/jdk/com/sun/net/httpserver/bugs/ExceptionKeepAlive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,6 @@ * questions. */ -/** - * @test - * @bug 8219083 - * @summary Exceptions thrown from HttpHandler.handle should not close connection - * if response is completed - * @library /test/lib - * @run junit ExceptionKeepAlive - */ - import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; @@ -42,20 +33,35 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; +import java.util.logging.ConsoleHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; -import java.util.logging.StreamHandler; import static org.junit.jupiter.api.Assertions.*; import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; -public class ExceptionKeepAlive -{ +/* + * @test + * @bug 8219083 + * @summary Exceptions thrown from HttpHandler.handle should not close connection + * if response is completed + * @library /test/lib + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run junit/othervm ${test.main.class} + */ +public class ExceptionKeepAlive { public static final Logger LOGGER = Logger.getLogger("com.sun.net.httpserver"); + private static void setupLogging() { + final Handler handler = new ConsoleHandler(); + handler.setLevel(Level.FINEST); + LOGGER.setLevel(Level.FINEST); + LOGGER.addHandler(handler); + } + @Test void test() throws IOException, InterruptedException { HttpServer httpServer = startHttpServer(); @@ -89,11 +95,7 @@ public class ExceptionKeepAlive * Http Server */ HttpServer startHttpServer() throws IOException { - Handler outHandler = new StreamHandler(System.out, - new SimpleFormatter()); - outHandler.setLevel(Level.FINEST); - LOGGER.setLevel(Level.FINEST); - LOGGER.addHandler(outHandler); + setupLogging(); // merely for debugging InetAddress loopback = InetAddress.getLoopbackAddress(); HttpServer httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0); httpServer.createContext("/", new MyHandler()); diff --git a/test/jdk/com/sun/net/httpserver/bugs/FixedLengthInputStream.java b/test/jdk/com/sun/net/httpserver/bugs/FixedLengthInputStream.java index c2195b3568f..c4287f50c9a 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/FixedLengthInputStream.java +++ b/test/jdk/com/sun/net/httpserver/bugs/FixedLengthInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,25 +21,14 @@ * questions. */ -/** - * @test - * @bug 6756771 6755625 - * @summary com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig - * @library /test/lib - * @run main FixedLengthInputStream - * @run main/othervm -Djava.net.preferIPv6Addresses=true FixedLengthInputStream - */ - import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; -import java.io.PrintStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.HttpURLConnection; import java.net.Proxy; import java.net.URL; -import java.net.Socket; import java.util.logging.*; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; @@ -47,10 +36,21 @@ import com.sun.net.httpserver.HttpServer; import jdk.test.lib.net.URIBuilder; import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; -public class FixedLengthInputStream -{ +/* + * @test + * @bug 6756771 6755625 + * @summary com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig + * @library /test/lib + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + * @run main/othervm -Djava.net.preferIPv6Addresses=true ${test.main.class} + */ +public class FixedLengthInputStream { static final long POST_SIZE = 4L * 1024L * 1024L * 1024L; // 4Gig + private static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); + void test(String[] args) throws IOException { HttpServer httpServer = startHttpServer(); int port = httpServer.getAddress().getPort(); @@ -89,18 +89,19 @@ public class FixedLengthInputStream } } + private static void setupLogging() { + final ConsoleHandler handler = new ConsoleHandler(); + handler.setLevel(Level.FINEST); + logger.setLevel(Level.FINEST); + logger.addHandler(handler); + } + /** * Http Server */ HttpServer startHttpServer() throws IOException { if (debug) { - Logger logger = - Logger.getLogger("com.sun.net.httpserver"); - Handler outHandler = new StreamHandler(System.out, - new SimpleFormatter()); - outHandler.setLevel(Level.FINEST); - logger.setLevel(Level.FINEST); - logger.addHandler(outHandler); + setupLogging(); // merely for debugging } InetAddress loopback = InetAddress.getLoopbackAddress(); HttpServer httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0); diff --git a/test/jdk/com/sun/net/httpserver/bugs/HandlerConnectionClose.java b/test/jdk/com/sun/net/httpserver/bugs/HandlerConnectionClose.java index 372e941904e..215a189c7bf 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/HandlerConnectionClose.java +++ b/test/jdk/com/sun/net/httpserver/bugs/HandlerConnectionClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,15 +21,6 @@ * questions. */ -/** - * @test - * @bug 8218554 - * @summary test that the handler can request a connection close. - * @library /test/lib - * @build jdk.test.lib.net.SimpleSSLContext - * @run main/othervm HandlerConnectionClose - */ - import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; @@ -49,22 +40,30 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Locale; +import java.util.logging.ConsoleHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; -import java.util.logging.StreamHandler; import jdk.test.lib.net.SimpleSSLContext; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; -public class HandlerConnectionClose -{ +/* + * @test + * @bug 8218554 + * @summary test that the handler can request a connection close. + * @library /test/lib + * @build jdk.test.lib.net.SimpleSSLContext + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + */ +public class HandlerConnectionClose { static final int ONEK = 1024; static final long POST_SIZE = ONEK * 1L; private static final SSLContext sslContext = SimpleSSLContext.findSSLContext(); - Logger logger; + private static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); void test(String[] args) throws Exception { @@ -341,17 +340,20 @@ public class HandlerConnectionClose } } + private static void setupLogging() { + final Handler handler = new ConsoleHandler(); + handler.setLevel(Level.FINEST); + logger.setLevel(Level.FINEST); + logger.addHandler(handler); + + } + /** * Http Server */ HttpServer startHttpServer(String protocol) throws IOException { if (debug) { - logger = Logger.getLogger("com.sun.net.httpserver"); - Handler outHandler = new StreamHandler(System.out, - new SimpleFormatter()); - outHandler.setLevel(Level.FINEST); - logger.setLevel(Level.FINEST); - logger.addHandler(outHandler); + setupLogging(); // merely for debugging } InetSocketAddress serverAddress = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); diff --git a/test/jdk/com/sun/net/httpserver/bugs/HeadKeepAlive.java b/test/jdk/com/sun/net/httpserver/bugs/HeadKeepAlive.java index 4d987ada173..c575fdfc810 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/HeadKeepAlive.java +++ b/test/jdk/com/sun/net/httpserver/bugs/HeadKeepAlive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,14 +21,6 @@ * questions. */ -/** - * @test - * @bug 8304963 - * @summary Connection should be reusable after HEAD request - * @library /test/lib - * @run junit HeadKeepAlive - */ - import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; @@ -41,19 +33,33 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; +import java.util.logging.ConsoleHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; -import java.util.logging.StreamHandler; import static org.junit.jupiter.api.Assertions.*; import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; -public class HeadKeepAlive -{ +/* + * @test + * @bug 8304963 + * @summary Connection should be reusable after HEAD request + * @library /test/lib + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run junit/othervm ${test.main.class} + */ +public class HeadKeepAlive { - public static final Logger LOGGER = Logger.getLogger("com.sun.net.httpserver"); + private static final Logger LOGGER = Logger.getLogger("com.sun.net.httpserver"); + + private static void setupLogging() { + final Handler handler = new ConsoleHandler(); + handler.setLevel(Level.FINEST); + LOGGER.setLevel(Level.FINEST); + LOGGER.addHandler(handler); + } @Test void test() throws IOException, InterruptedException { @@ -90,11 +96,7 @@ public class HeadKeepAlive * Http Server */ HttpServer startHttpServer() throws IOException { - Handler outHandler = new StreamHandler(System.out, - new SimpleFormatter()); - outHandler.setLevel(Level.FINEST); - LOGGER.setLevel(Level.FINEST); - LOGGER.addHandler(outHandler); + setupLogging(); // merely for debugging InetAddress loopback = InetAddress.getLoopbackAddress(); HttpServer httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0); httpServer.createContext("/", new MyHandler()); diff --git a/test/jdk/com/sun/net/httpserver/bugs/TruncatedRequestBody.java b/test/jdk/com/sun/net/httpserver/bugs/TruncatedRequestBody.java index 824428755a4..95a3d1787df 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/TruncatedRequestBody.java +++ b/test/jdk/com/sun/net/httpserver/bugs/TruncatedRequestBody.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,6 @@ * questions. */ -/** - * @test - * @bug 8190793 - * @summary Httpserver does not detect truncated request body - */ import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; @@ -46,12 +41,23 @@ import java.util.logging.Level; import java.util.logging.Logger; import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; +/* + * @test + * @bug 8190793 + * @summary Httpserver does not detect truncated request body + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run main/othervm ${test.main.class} + */ /* * Send two POST requests to the server which are both trucated * and socket closed. Server needs to detect this and throw an IOException * in getRequestBody().read(). Two variants for fixed length and chunked. */ public class TruncatedRequestBody { + + private static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); + static volatile boolean error = false; static CountDownLatch latch = new CountDownLatch(2); @@ -81,16 +87,18 @@ public class TruncatedRequestBody { } + private static void setupLogging() { + final ConsoleHandler h = new ConsoleHandler(); + h.setLevel(Level.ALL); + logger.setLevel(Level.ALL); + logger.addHandler(h); + } + /** * @param args the command line arguments */ public static void main(String[] args) throws IOException, InterruptedException { - Logger logger = Logger.getLogger("com.sun.net.httpserver"); - ConsoleHandler h = new ConsoleHandler(); - h.setLevel(Level.ALL); - logger.setLevel(Level.ALL); - logger.addHandler(h); - + setupLogging(); // merely for debugging InetAddress loopback = InetAddress.getLoopbackAddress(); InetSocketAddress addr = new InetSocketAddress(loopback, 0); HttpServer server = HttpServer.create(addr, 10); diff --git a/test/jdk/com/sun/net/httpserver/bugs/ZeroLengthOutputStream.java b/test/jdk/com/sun/net/httpserver/bugs/ZeroLengthOutputStream.java index 33bbe0479db..0715800ead7 100644 --- a/test/jdk/com/sun/net/httpserver/bugs/ZeroLengthOutputStream.java +++ b/test/jdk/com/sun/net/httpserver/bugs/ZeroLengthOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,14 +21,6 @@ * questions. */ -/** - * @test - * @bug 8219083 - * @summary HttpExchange.getResponseBody write and close should not throw - * even when response length is zero - * @library /test/lib - * @run junit ZeroLengthOutputStream - */ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; @@ -44,19 +36,27 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; import java.util.concurrent.CountDownLatch; +import java.util.logging.ConsoleHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; -import java.util.logging.StreamHandler; import static org.junit.jupiter.api.Assertions.*; import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; -public class ZeroLengthOutputStream -{ +/* + * @test + * @bug 8219083 + * @summary HttpExchange.getResponseBody write and close should not throw + * even when response length is zero + * @library /test/lib + * @comment We use othervm because this test configures logging handlers + * for the system wide "com.sun.net.httpserver" logger + * @run junit/othervm ${test.main.class} + */ +public class ZeroLengthOutputStream { - public static final Logger LOGGER = Logger.getLogger("com.sun.net.httpserver"); + private static final Logger LOGGER = Logger.getLogger("com.sun.net.httpserver"); public volatile boolean closed; public CountDownLatch cdl = new CountDownLatch(1); @@ -80,15 +80,18 @@ public class ZeroLengthOutputStream } } + private static void setupLogging() { + final Handler handler = new ConsoleHandler(); + handler.setLevel(Level.FINEST); + LOGGER.setLevel(Level.FINEST); + LOGGER.addHandler(handler); + } + /** * Http Server */ HttpServer startHttpServer() throws IOException { - Handler outHandler = new StreamHandler(System.out, - new SimpleFormatter()); - outHandler.setLevel(Level.FINEST); - LOGGER.setLevel(Level.FINEST); - LOGGER.addHandler(outHandler); + setupLogging(); // merely for debugging InetAddress loopback = InetAddress.getLoopbackAddress(); HttpServer httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0); httpServer.createContext("/flis/", new MyHandler()); From 5e8bba3ae7a2f5c61c56deb2072425b003d7d7c4 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 11 Mar 2026 05:39:03 +0000 Subject: [PATCH 163/170] 8379456: Test jdk/jfr/event/runtime/TestVMInfoEvent.java now fails with java.lang.NoClassDefFoundError: java/lang/management/ManagementFactory Reviewed-by: lmesnik --- test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java b/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java index 8cbc6ea2bb8..ebee42b52df 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestVMInfoEvent.java @@ -40,6 +40,7 @@ import jdk.test.lib.jfr.Events; /** * @test * @modules java.base/jdk.internal.vm + * @modules java.management * @requires vm.flagless * @requires vm.gc == "Serial" | vm.gc == null * @requires vm.hasJFR From a741e290c9cf95465447a913880d6b1ad45e6f9a Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 11 Mar 2026 07:15:25 +0000 Subject: [PATCH 164/170] 8379284: Avoid the need to keep obsolete preview feature constants until bootstrap JDK is upgraded Reviewed-by: liach, erikj, jpai, vromero --- make/CompileInterimLangtools.gmk | 25 ++--- .../previewfeature/SetupPreviewFeature.java | 93 +++++++++++++++++++ .../jdk/internal/javac/PreviewFeature.java | 21 +---- 3 files changed, 108 insertions(+), 31 deletions(-) create mode 100644 make/langtools/tools/previewfeature/SetupPreviewFeature.java diff --git a/make/CompileInterimLangtools.gmk b/make/CompileInterimLangtools.gmk index c7d1c3796f6..8254b8fc0a7 100644 --- a/make/CompileInterimLangtools.gmk +++ b/make/CompileInterimLangtools.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -68,17 +68,19 @@ java.compiler.interim_EXTRA_FILES := \ TARGETS += $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.compiler.interim/javax/tools/ToolProvider.java ################################################################################ -# Use the up-to-date PreviewFeature.java and NoPreview.java from the current -# sources, instead of the versions from the boot JDK, as javac may be referring -# to constants from the up-to-date versions. +# Create a hybrid PreviewFeature.java that combines constants +# from the current sources, as those can be used in javac APIs, and from the +# bootstrap JDK, as those can be used from bootstrap JDK classfiles. -$(eval $(call SetupCopyFiles, COPY_PREVIEW_FEATURES, \ - FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \ - $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/NoPreview.java, \ - DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/, \ -)) +$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java: \ + $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java + $(call LogInfo, Generating $@) + $(JAVA) $(TOPDIR)/make/langtools/tools/previewfeature/SetupPreviewFeature.java \ + $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \ + $@ -TARGETS += $(COPY_PREVIEW_FEATURES) + +TARGETS += $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java ################################################################################ # Setup the rules to build interim langtools, which is compiled by the boot @@ -123,7 +125,8 @@ define SetupInterimModule $1_DEPS_INTERIM := $$(addsuffix .interim, $$(filter \ $$(INTERIM_LANGTOOLS_BASE_MODULES), $$(call FindTransitiveDepsForModule, $1))) - $$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d)) $(COPY_PREVIEW_FEATURES) + $$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d)) \ + $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java TARGETS += $$(BUILD_$1.interim) endef diff --git a/make/langtools/tools/previewfeature/SetupPreviewFeature.java b/make/langtools/tools/previewfeature/SetupPreviewFeature.java new file mode 100644 index 00000000000..2d5207f0e17 --- /dev/null +++ b/make/langtools/tools/previewfeature/SetupPreviewFeature.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package previewfeature; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.Trees; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import javax.lang.model.element.ElementKind; +import javax.tools.ToolProvider; + +/* Construct a hybrid PreviewFeature.Feature enum that includes constants both + * from the current JDK sources (so that they can be used in the javac API sources), + * and from the bootstrap JDK (so that they can be used in the bootstrap classfiles). + * + * This hybrid enum is only used for the interim javac. + */ +public class SetupPreviewFeature { + public static void main(String... args) throws Exception { + Class runtimeFeature = Class.forName("jdk.internal.javac.PreviewFeature$Feature"); + Set constantsToAdd = new HashSet<>(); + for (Field runtimeField : runtimeFeature.getDeclaredFields()) { + if (runtimeField.isEnumConstant()) { + constantsToAdd.add(runtimeField.getName()); + } + } + var dummy = new StringWriter(); + var compiler = ToolProvider.getSystemJavaCompiler(); + var source = Path.of(args[0]); + try (var fm = compiler.getStandardFileManager(null, null, null)) { + JavacTask task = + (JavacTask) compiler.getTask(dummy, null, null, null, null, fm.getJavaFileObjects(source)); + task.analyze(); + var sourceFeature = task.getElements() + .getTypeElement("jdk.internal.javac.PreviewFeature.Feature"); + int insertPosition = -1; + for (var el : sourceFeature.getEnclosedElements()) { + if (el.getKind() == ElementKind.ENUM_CONSTANT) { + constantsToAdd.remove(el.getSimpleName().toString()); + if (insertPosition == (-1)) { + var trees = Trees.instance(task); + var elPath = trees.getPath(el); + insertPosition = (int) trees.getSourcePositions() + .getStartPosition(elPath.getCompilationUnit(), + elPath.getLeaf()); + } + } + } + var target = Path.of(args[1]); + Files.createDirectories(target.getParent()); + if (constantsToAdd.isEmpty()) { + Files.copy(source, target); + } else { + String sourceCode = Files.readString(source); + try (var out = Files.newBufferedWriter(target)) { + out.write(sourceCode, 0, insertPosition); + out.write(constantsToAdd.stream() + .collect(Collectors.joining(", ", + "/*compatibility constants:*/ ", + ",\n"))); + out.write(sourceCode, insertPosition, sourceCode.length() - insertPosition); + } + } + } + } +} \ No newline at end of file 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 5942cefa2a1..a698440c15d 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,25 +64,6 @@ public @interface PreviewFeature { * Values should be annotated with the feature's {@code JEP}. */ public enum Feature { - // The JDK build process involves creating an interim javac which is then - // used to compile the rest of the JDK. The jdk.internal.javac.PreviewFeature - // annotation from the current sources is used when compiling interim javac. - // That's because the javac APIs of the current sources may be annotated with - // this annotation and they may be using the enum constants of the current sources. - // Furthermore, when compiling interim javac, the class files from the bootstrap JDK get - // used and those may also contain the PreviewFeature annotation. However, they may be - // using the enum constants of the bootstrap JDK's PreviewFeature annotation. - // If javac sees an annotation with an unknown enum constant, it produces a warning, - // and that in turn fails the build. - // So, in the current sources, we need to preserve the PreviewFeature enum constants - // for as long as the interim javac build needs it. As a result, we retain PreviewFeature - // enum constants for preview features that are present in the bootstrap JDK. - // Older constants can be removed. - // - // For example, Class-File API became final in JDK 24. As soon as JDK 23 was dropped as - // the bootstrap JDK, the CLASSFILE_API enum constant became eligible for removal. - - //--- @JEP(number=525, title="Structured Concurrency", status="Sixth Preview") STRUCTURED_CONCURRENCY, @JEP(number = 526, title = "Lazy Constants", status = "Second Preview") From 619fe63b5f112b9c7f3d2755504c70fd4bebade3 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Wed, 11 Mar 2026 08:39:41 +0000 Subject: [PATCH 165/170] 8362239: Reconcile enter_internal and reenter_internal in the ObjectMonitor code Reviewed-by: dholmes, fbredberg, coleenp, pchilanomate, dcubed --- src/hotspot/share/runtime/objectMonitor.cpp | 255 ++++++++------------ src/hotspot/share/runtime/objectMonitor.hpp | 4 +- 2 files changed, 102 insertions(+), 157 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index cb69b82d767..94399088464 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -593,12 +593,15 @@ void ObjectMonitor::enter_with_contention_mark(JavaThread* current, ObjectMonito OSThreadContendState osts(current->osthread()); assert(current->thread_state() == _thread_in_vm, "invariant"); + ObjectWaiter node(current); for (;;) { ExitOnSuspend eos(this); { ThreadBlockInVMPreprocess tbivs(current, eos, true /* allow_suspend */); - enter_internal(current); + if (!try_enter_fast(current, &node)) { + enter_internal(current, &node, false /* reenter_path */); + } current->set_current_pending_monitor(nullptr); // We can go to a safepoint at the end of this block. If we // do a thread dump during that safepoint, then this thread will show @@ -942,14 +945,17 @@ const char* ObjectMonitor::is_busy_to_string(stringStream* ss) { return ss->base(); } -void ObjectMonitor::enter_internal(JavaThread* current) { +bool ObjectMonitor::try_enter_fast(JavaThread* current, ObjectWaiter* current_node) { + assert(current != nullptr, "invariant"); assert(current->thread_state() == _thread_blocked, "invariant"); + assert(current_node != nullptr, "invariant"); + assert(current_node->_thread == current, "invariant"); // Try the lock - TATAS if (try_lock(current) == TryLockResult::Success) { assert(!has_successor(current), "invariant"); assert(has_owner(current), "invariant"); - return; + return true; } assert(InitDone, "Unexpectedly not initialized"); @@ -964,7 +970,7 @@ void ObjectMonitor::enter_internal(JavaThread* current) { if (try_spin(current)) { assert(has_owner(current), "invariant"); assert(!has_successor(current), "invariant"); - return; + return true; } // The Spin failed -- Enqueue and park the thread ... @@ -973,54 +979,67 @@ void ObjectMonitor::enter_internal(JavaThread* current) { // Enqueue "current" on ObjectMonitor's _entry_list. // - // Node acts as a proxy for current. + // current_node acts as a proxy for current. // As an aside, if were to ever rewrite the synchronization code mostly // in Java, WaitNodes, ObjectMonitors, and Events would become 1st-class // Java objects. This would avoid awkward lifecycle and liveness issues, // as well as eliminate a subset of ABA issues. // TODO: eliminate ObjectWaiter and enqueue either Threads or Events. - ObjectWaiter node(current); current->_ParkEvent->reset(); - if (try_lock_or_add_to_entry_list(current, &node)) { - return; // We got the lock. + if (try_lock_or_add_to_entry_list(current, current_node)) { + return true; // We got the lock. } + // This thread is now added to the _entry_list. // The lock might have been released while this thread was occupied queueing // itself onto _entry_list. To close the race and avoid "stranding" and - // progress-liveness failure we must resample-retry _owner before parking. + // progress-liveness failure the caller must resample-retry _owner before parking. // Note the Dekker/Lamport duality: ST _entry_list; MEMBAR; LD Owner. - // In this case the ST-MEMBAR is accomplished with CAS(). - // - // TODO: Defer all thread state transitions until park-time. - // Since state transitions are heavy and inefficient we'd like - // to defer the state transitions until absolutely necessary, - // and in doing so avoid some transitions ... + // In this case the ST-MEMBAR is accomplished with CAS() in try_lock_or_add_to_entry_list. + return false; +} + +void ObjectMonitor::enter_internal(JavaThread* current, ObjectWaiter* current_node, bool reenter_path) { + assert(current != nullptr, "invariant"); + assert(current->thread_state() == _thread_blocked, "invariant"); + assert(current_node != nullptr, "invariant"); + assert(current_node->_thread == current, "invariant"); // If there are unmounted virtual threads ahead in the _entry_list we want // to do a timed-park instead to alleviate some deadlock cases where one // of them is picked as the successor but cannot run due to having run out // of carriers. This can happen, for example, if this is a pinned virtual - // thread currently loading or initializining a class, and all other carriers + // thread currently loading or initializing a class, and all other carriers // have a pinned vthread waiting for said class to be loaded/initialized. // Read counter *after* adding this thread to the _entry_list. Adding to // _entry_list uses Atomic::cmpxchg() which already provides a fence that - // prevents this load from floating up previous store. + // prevents this load from floating up past a previous store. // Note that we can have false positives where timed-park is not necessary. - bool do_timed_parked = has_unmounted_vthreads(); + bool do_timed_park = has_unmounted_vthreads(); jlong recheck_interval = 1; for (;;) { + ObjectWaiter::TStates v = current_node->TState; + guarantee(v == ObjectWaiter::TS_ENTER, "invariant"); if (try_lock(current) == TryLockResult::Success) { break; } assert(!has_owner(current), "invariant"); + if (reenter_path) { + // If try_lock failed, spin again - we expect the notifier to release the monitor quickly. + // Note that spin count may be zero so the above try_lock is necessary. + if (try_spin(current)) { + break; + } + } + // park self - if (do_timed_parked) { + if (do_timed_park) { current->_ParkEvent->park(recheck_interval); // Increase the recheck_interval, but clamp the value. recheck_interval *= 8; @@ -1031,125 +1050,6 @@ void ObjectMonitor::enter_internal(JavaThread* current) { current->_ParkEvent->park(); } - if (try_lock(current) == TryLockResult::Success) { - break; - } - - // The lock is still contested. - - // Assuming this is not a spurious wakeup we'll normally find _succ == current. - // We can defer clearing _succ until after the spin completes - // try_spin() must tolerate being called with _succ == current. - // Try yet another round of adaptive spinning. - if (try_spin(current)) { - break; - } - - // We can find that we were unpark()ed and redesignated _succ while - // we were spinning. That's harmless. If we iterate and call park(), - // park() will consume the event and return immediately and we'll - // just spin again. This pattern can repeat, leaving _succ to simply - // spin on a CPU. - - if (has_successor(current)) clear_successor(); - - // Invariant: after clearing _succ a thread *must* retry _owner before parking. - OrderAccess::fence(); - } - - // Egress : - // Current has acquired the lock -- Unlink current from the _entry_list. - unlink_after_acquire(current, &node); - if (has_successor(current)) { - clear_successor(); - // Note that we don't need to do OrderAccess::fence() after clearing - // _succ here, since we own the lock. - } - - // We've acquired ownership with CAS(). - // CAS is serializing -- it has MEMBAR/FENCE-equivalent semantics. - // But since the CAS() this thread may have also stored into _succ - // or entry_list. These meta-data updates must be visible __before - // this thread subsequently drops the lock. - // Consider what could occur if we didn't enforce this constraint -- - // STs to monitor meta-data and user-data could reorder with (become - // visible after) the ST in exit that drops ownership of the lock. - // Some other thread could then acquire the lock, but observe inconsistent - // or old monitor meta-data and heap data. That violates the JMM. - // To that end, the exit() operation must have at least STST|LDST - // "release" barrier semantics. Specifically, there must be at least a - // STST|LDST barrier in exit() before the ST of null into _owner that drops - // the lock. The barrier ensures that changes to monitor meta-data and data - // protected by the lock will be visible before we release the lock, and - // therefore before some other thread (CPU) has a chance to acquire the lock. - // See also: http://gee.cs.oswego.edu/dl/jmm/cookbook.html. - // - // Critically, any prior STs to _succ or entry_list must be visible before - // the ST of null into _owner in the *subsequent* (following) corresponding - // monitorexit. - - return; -} - -// reenter_internal() is a specialized inline form of the latter half of the -// contended slow-path from enter_internal(). We use reenter_internal() only for -// monitor reentry in wait(). -// -// In the future we should reconcile enter_internal() and reenter_internal(). - -void ObjectMonitor::reenter_internal(JavaThread* current, ObjectWaiter* currentNode) { - assert(current != nullptr, "invariant"); - assert(current->thread_state() == _thread_blocked, "invariant"); - assert(currentNode != nullptr, "invariant"); - assert(currentNode->_thread == current, "invariant"); - assert(_waiters > 0, "invariant"); - - // If there are unmounted virtual threads ahead in the _entry_list we want - // to do a timed-park instead to alleviate some deadlock cases where one - // of them is picked as the successor but cannot run due to having run out - // of carriers. This can happen, for example, if a mixed of unmounted and - // pinned vthreads taking up all the carriers are waiting for a class to be - // initialized, and the selected successor is one of the unmounted vthreads. - // Although this method is used for the "notification" case, it could be - // that this thread reached here without been added to the _entry_list yet. - // This can happen if it was interrupted or the wait timed-out at the same - // time. In that case we rely on currentNode->_do_timed_park, which will be - // read on the next loop iteration, after consuming the park permit set by - // the notifier in notify_internal. - // Note that we can have false positives where timed-park is not necessary. - bool do_timed_parked = has_unmounted_vthreads(); - jlong recheck_interval = 1; - - for (;;) { - ObjectWaiter::TStates v = currentNode->TState; - guarantee(v == ObjectWaiter::TS_ENTER, "invariant"); - assert(!has_owner(current), "invariant"); - - // This thread has been notified so try to reacquire the lock. - if (try_lock(current) == TryLockResult::Success) { - break; - } - - // If that fails, spin again. Note that spin count may be zero so the above TryLock - // is necessary. - if (try_spin(current)) { - break; - } - - { - OSThreadContendState osts(current->osthread()); - if (do_timed_parked) { - current->_ParkEvent->park(recheck_interval); - // Increase the recheck_interval, but clamp the value. - recheck_interval *= 8; - if (recheck_interval > MAX_RECHECK_INTERVAL) { - recheck_interval = MAX_RECHECK_INTERVAL; - } - } else { - current->_ParkEvent->park(); - } - } - // Try again, but just so we distinguish between futile wakeups and // successful wakeups. The following test isn't algorithmically // necessary, but it helps us maintain sensible statistics. @@ -1159,25 +1059,68 @@ void ObjectMonitor::reenter_internal(JavaThread* current, ObjectWaiter* currentN // The lock is still contested. - // Assuming this is not a spurious wakeup we'll normally - // find that _succ == current. - if (has_successor(current)) clear_successor(); + if (!reenter_path) { + // Assuming this is not a spurious wakeup we'll normally find _succ == current. + // We can defer clearing _succ until after the spin completes and + // try_spin() must tolerate being called with _succ == current. + // Try yet another round of adaptive spinning. + if (try_spin(current)) { + break; + } + } - // Invariant: after clearing _succ a contending thread - // *must* retry _owner before parking. + // We can find that we were unpark()ed and redesignated _succ while + // we were spinning. That's harmless. If we iterate and call park(), + // park() will consume the event and return immediately and we'll + // just spin again. This pattern can repeat, leaving _succ to simply + // spin on a CPU. + + if (has_successor(current)) { + clear_successor(); + } + + // Invariant: after clearing _succ a thread *must* retry _owner before parking. OrderAccess::fence(); - // See comment in notify_internal - do_timed_parked |= currentNode->_do_timed_park; + // Will only potentially change on the reenter path - see comment in notify_internal. + do_timed_park |= current_node->_do_timed_park; } - // Current has acquired the lock -- Unlink current from the _entry_list. assert(has_owner(current), "invariant"); - unlink_after_acquire(current, currentNode); - if (has_successor(current)) clear_successor(); - assert(!has_successor(current), "invariant"); - currentNode->TState = ObjectWaiter::TS_RUN; - OrderAccess::fence(); // see comments at the end of enter_internal() + + // Egress : + // Current has acquired the lock -- Unlink current from the _entry_list. + unlink_after_acquire(current, current_node); + if (has_successor(current)) { + clear_successor(); + // Note that we don't need to do OrderAccess::fence() after clearing + // _succ here, since we own the lock. + } + + // We've acquired ownership with CAS(). + // CAS is serializing -- it has MEMBAR/FENCE-equivalent semantics. + // But since the CAS() this thread may have also stored into _succ + // or entry_list. These meta-data updates must be visible __before + // this thread subsequently drops the lock. + // Consider what could occur if we didn't enforce this constraint -- + // STs to monitor meta-data and user-data could reorder with (become + // visible after) the ST in exit that drops ownership of the lock. + // Some other thread could then acquire the lock, but observe inconsistent + // or old monitor meta-data and heap data. That violates the JMM. + // To that end, the exit() operation must have at least STST|LDST + // "release" barrier semantics. Specifically, there must be at least a + // STST|LDST barrier in exit() before the ST of null into _owner that drops + // the lock. The barrier ensures that changes to monitor meta-data and data + // protected by the lock will be visible before we release the lock, and + // therefore before some other thread (CPU) has a chance to acquire the lock. + // See also: http://gee.cs.oswego.edu/dl/jmm/cookbook.html. + // + // Critically, any prior STs to _succ or entry_list must be visible before + // the ST of null into _owner in the *subsequent* (following) corresponding + // monitorexit. + + current_node->TState = ObjectWaiter::TS_RUN; + return; } // This method is called from two places: @@ -1971,7 +1914,9 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { ExitOnSuspend eos(this); { ThreadBlockInVMPreprocess tbivs(current, eos, true /* allow_suspend */); - reenter_internal(current, &node); + assert( _waiters > 0, "invariant"); + OSThreadContendState osts(current->osthread()); + enter_internal(current, &node, true /* reenter_path */); // We can go to a safepoint at the end of this block. If we // do a thread dump during that safepoint, then this thread will show // as having "-locked" the monitor, but the OS and java.lang.Thread @@ -2082,12 +2027,12 @@ bool ObjectMonitor::notify_internal(JavaThread* current) { // Wake up the thread to alleviate some deadlock cases where the successor // that will be picked up when this thread releases the monitor is an unmounted // virtual thread that cannot run due to having run out of carriers. Upon waking - // up, the thread will call reenter_internal() which will use timed-park in case + // up, the thread will call enter_internal(..., true) which will use timed-park in case // there is contention and there are still vthreads in the _entry_list. // If the target was interrupted or the wait timed-out at the same time, it could - // have reached reenter_internal and read a false value of has_unmounted_vthreads() + // have reached enter_internal and read a false value of has_unmounted_vthreads() // before we added it to the _entry_list above. To deal with that case, we set _do_timed_park - // which will be read by the target on the next loop iteration in reenter_internal. + // which will be read by the target on the next loop iteration in enter_internal. iterator->_do_timed_park = true; JavaThread* t = iterator->thread(); t->_ParkEvent->unpark(); diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 8d9a481bf37..842aa1b374e 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -394,8 +394,8 @@ class ObjectMonitor : public CHeapObj { bool notify_internal(JavaThread* current); ObjectWaiter* dequeue_waiter(); void dequeue_specific_waiter(ObjectWaiter* waiter); - void enter_internal(JavaThread* current); - void reenter_internal(JavaThread* current, ObjectWaiter* current_node); + void enter_internal(JavaThread* current, ObjectWaiter* current_node, bool reenter_path); + bool try_enter_fast(JavaThread* current, ObjectWaiter* current_node); void entry_list_build_dll(JavaThread* current); void unlink_after_acquire(JavaThread* current, ObjectWaiter* current_node); ObjectWaiter* entry_list_tail(JavaThread* current); From e74863249cad05d3afdd16d0d6e3107040c62e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20H=C3=BCbner?= Date: Wed, 11 Mar 2026 09:22:20 +0000 Subject: [PATCH 166/170] 8378559: Add setting of captured states like errno Reviewed-by: jvernee, fbredberg --- .../cpu/aarch64/downcallLinker_aarch64.cpp | 50 ++++++++++++++---- src/hotspot/cpu/ppc/downcallLinker_ppc.cpp | 47 +++++++++++++---- .../cpu/riscv/downcallLinker_riscv.cpp | 49 ++++++++++++++---- src/hotspot/cpu/s390/downcallLinker_s390.cpp | 45 ++++++++++++---- src/hotspot/cpu/x86/downcallLinker_x86_64.cpp | 48 +++++++++++++---- src/hotspot/share/prims/downcallLinker.cpp | 37 ++++++++++---- src/hotspot/share/prims/downcallLinker.hpp | 7 +-- .../classes/java/lang/foreign/Linker.java | 32 +++++++----- .../native/libfallbackLinker/fallbackLinker.c | 43 ++++++++++++---- .../TestCaptureCallState.java | 51 ++++++++++++------- .../capturecallstate/libCaptureCallState.c | 14 ++++- 11 files changed, 319 insertions(+), 104 deletions(-) diff --git a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp index 65d448f908c..130d2949800 100644 --- a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -146,10 +146,10 @@ void DowncallLinker::StubGenerator::generate() { bool should_save_return_value = !_needs_return_buffer; RegSpiller out_reg_spiller(_output_registers); - int spill_offset = -1; + int out_spill_offset = -1; if (should_save_return_value) { - spill_offset = 0; + out_spill_offset = 0; // spill area can be shared with shadow space and out args, // since they are only used before the call, // and spill area is only used after. @@ -174,6 +174,9 @@ void DowncallLinker::StubGenerator::generate() { // FP-> | | // |---------------------| = frame_bottom_offset = frame_size // | (optional) | + // | in_reg_spiller area | + // |---------------------| + // | (optional) | // | capture state buf | // |---------------------| = StubLocations::CAPTURED_STATE_BUFFER // | (optional) | @@ -187,6 +190,19 @@ void DowncallLinker::StubGenerator::generate() { GrowableArray out_regs = ForeignGlobals::replace_place_holders(_input_registers, locs); ArgumentShuffle arg_shuffle(filtered_java_regs, out_regs, shuffle_reg); + // Need to spill for state capturing runtime call. + // The area spilled into is distinct from the capture state buffer. + RegSpiller in_reg_spiller(out_regs); + int in_spill_offset = -1; + if (_captured_state_mask != 0) { + // The spill area cannot be shared with the out_spill since + // spilling needs to happen before the call. Allocate a new + // region in the stack for this spill space. + in_spill_offset = allocated_frame_size; + allocated_frame_size += in_reg_spiller.spill_size_bytes(); + } + + #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; if (lt.is_enabled()) { @@ -228,6 +244,20 @@ void DowncallLinker::StubGenerator::generate() { arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes); __ block_comment("} argument shuffle"); + if (_captured_state_mask != 0) { + assert(in_spill_offset != -1, "must be"); + __ block_comment("{ load initial thread local"); + in_reg_spiller.generate_spill(_masm, in_spill_offset); + + // Copy the contents of the capture state buffer into thread local + __ ldr(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ movw(c_rarg1, _captured_state_mask); + __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_pre), tmp1); + + in_reg_spiller.generate_fill(_masm, in_spill_offset); + __ block_comment("} load initial thread local"); + } + __ blr(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); // this call is assumed not to have killed rthread @@ -254,15 +284,15 @@ void DowncallLinker::StubGenerator::generate() { __ block_comment("{ save thread local"); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ ldr(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); __ movw(c_rarg1, _captured_state_mask); - __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state), tmp1); + __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_post), tmp1); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ block_comment("} save thread local"); @@ -321,7 +351,7 @@ void DowncallLinker::StubGenerator::generate() { if (should_save_return_value) { // Need to save the native result registers around any runtime calls. - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ mov(c_rarg0, rthread); @@ -330,7 +360,7 @@ void DowncallLinker::StubGenerator::generate() { __ blr(tmp1); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ b(L_after_safepoint_poll); @@ -342,13 +372,13 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_reguard); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), tmp1); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ b(L_after_reguard); diff --git a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp index f12d25ac611..d149fc33ac3 100644 --- a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp +++ b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, 2025 SAP SE. All rights reserved. - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,10 +135,10 @@ void DowncallLinker::StubGenerator::generate() { bool should_save_return_value = !_needs_return_buffer; RegSpiller out_reg_spiller(_output_registers); - int spill_offset = -1; + int out_spill_offset = -1; if (should_save_return_value) { - spill_offset = frame::native_abi_reg_args_size; + out_spill_offset = frame::native_abi_reg_args_size; // Spill area can be shared with additional out args (>8), // since it is only used after the call. int frame_size_including_spill_area = frame::native_abi_reg_args_size + out_reg_spiller.spill_size_bytes(); @@ -170,6 +170,18 @@ void DowncallLinker::StubGenerator::generate() { ArgumentShuffle arg_shuffle(filtered_java_regs, out_regs, _abi._scratch1); + // Need to spill for state capturing runtime call. + // The area spilled into is distinct from the capture state buffer. + RegSpiller in_reg_spiller(out_regs); + int in_spill_offset = -1; + if (_captured_state_mask != 0) { + // The spill area cannot be shared with the out_spill since + // spilling needs to happen before the call. Allocate a new + // region in the stack for this spill space. + in_spill_offset = allocated_frame_size; + allocated_frame_size += in_reg_spiller.spill_size_bytes(); + } + #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; if (lt.is_enabled()) { @@ -211,6 +223,21 @@ void DowncallLinker::StubGenerator::generate() { arg_shuffle.generate(_masm, as_VMStorage(callerSP), frame::jit_out_preserve_size, frame::native_abi_minframe_size); __ block_comment("} argument shuffle"); + if (_captured_state_mask != 0) { + assert(in_spill_offset != -1, "must be"); + __ block_comment("{ load initial thread local"); + in_reg_spiller.generate_spill(_masm, in_spill_offset); + + // Copy the contents of the capture state buffer into thread local + __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, DowncallLinker::capture_state_pre), R0); + __ ld(R3_ARG1, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER), R1_SP); + __ load_const_optimized(R4_ARG2, _captured_state_mask, R0); + __ call_c(call_target_address); + + in_reg_spiller.generate_fill(_masm, in_spill_offset); + __ block_comment("} load initial thread local"); + } + __ call_c(call_target_address); if (_needs_return_buffer) { @@ -247,16 +274,16 @@ void DowncallLinker::StubGenerator::generate() { __ block_comment("{ save thread local"); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } - __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, DowncallLinker::capture_state), R0); + __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, DowncallLinker::capture_state_post), R0); __ ld(R3_ARG1, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER), R1_SP); __ load_const_optimized(R4_ARG2, _captured_state_mask, R0); __ call_c(call_target_address); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ block_comment("} save thread local"); @@ -310,7 +337,7 @@ void DowncallLinker::StubGenerator::generate() { if (should_save_return_value) { // Need to save the native result registers around any runtime calls. - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, JavaThread::check_special_condition_for_native_trans), R0); @@ -318,7 +345,7 @@ void DowncallLinker::StubGenerator::generate() { __ call_c(call_target_address); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ b(L_after_safepoint_poll); @@ -330,14 +357,14 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_reguard); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, SharedRuntime::reguard_yellow_pages), R0); __ call_c(call_target_address); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ b(L_after_reguard); diff --git a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp index cc685645ec5..f9d7ce78ff0 100644 --- a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -140,10 +140,10 @@ void DowncallLinker::StubGenerator::generate() { bool should_save_return_value = !_needs_return_buffer; RegSpiller out_reg_spiller(_output_registers); - int spill_offset = -1; + int out_spill_offset = -1; if (should_save_return_value) { - spill_offset = 0; + out_spill_offset = 0; // spill area can be shared with shadow space and out args, // since they are only used before the call, // and spill area is only used after. @@ -168,6 +168,9 @@ void DowncallLinker::StubGenerator::generate() { // FP-> | | // |---------------------| = frame_bottom_offset = frame_size // | (optional) | + // | in_reg_spiller area | + // |---------------------| + // | (optional) | // | capture state buf | // |---------------------| = StubLocations::CAPTURED_STATE_BUFFER // | (optional) | @@ -181,6 +184,18 @@ void DowncallLinker::StubGenerator::generate() { GrowableArray out_regs = ForeignGlobals::replace_place_holders(_input_registers, locs); ArgumentShuffle arg_shuffle(filtered_java_regs, out_regs, shuffle_reg); + // Need to spill for state capturing runtime call. + // The area spilled into is distinct from the capture state buffer. + RegSpiller in_reg_spiller(out_regs); + int in_spill_offset = -1; + if (_captured_state_mask != 0) { + // The spill area cannot be shared with the out_spill since + // spilling needs to happen before the call. Allocate a new + // region in the stack for this spill space. + in_spill_offset = allocated_frame_size; + allocated_frame_size += in_reg_spiller.spill_size_bytes(); + } + #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; if (lt.is_enabled()) { @@ -226,6 +241,20 @@ void DowncallLinker::StubGenerator::generate() { arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes); __ block_comment("} argument shuffle"); + if (_captured_state_mask != 0) { + assert(in_spill_offset != -1, "must be"); + __ block_comment("{ load initial thread local"); + in_reg_spiller.generate_spill(_masm, in_spill_offset); + + // Copy the contents of the capture state buffer into thread local + __ ld(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ mv(c_rarg1, _captured_state_mask); + __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_pre)); + + in_reg_spiller.generate_fill(_masm, in_spill_offset); + __ block_comment("} load initial thread local"); + } + __ jalr(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); // this call is assumed not to have killed xthread @@ -254,15 +283,15 @@ void DowncallLinker::StubGenerator::generate() { __ block_comment("{ save thread local"); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ ld(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); __ mv(c_rarg1, _captured_state_mask); - __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state)); + __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_post)); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ block_comment("} save thread local"); @@ -319,7 +348,7 @@ void DowncallLinker::StubGenerator::generate() { if (should_save_return_value) { // Need to save the native result registers around any runtime calls. - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ mv(c_rarg0, xthread); @@ -327,7 +356,7 @@ void DowncallLinker::StubGenerator::generate() { __ rt_call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ j(L_after_safepoint_poll); __ block_comment("} L_safepoint_poll_slow_path"); @@ -339,13 +368,13 @@ void DowncallLinker::StubGenerator::generate() { if (should_save_return_value) { // Need to save the native result registers around any runtime calls. - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); } __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); } __ j(L_after_reguard); diff --git a/src/hotspot/cpu/s390/downcallLinker_s390.cpp b/src/hotspot/cpu/s390/downcallLinker_s390.cpp index ccd8002da37..f1c41d05b5c 100644 --- a/src/hotspot/cpu/s390/downcallLinker_s390.cpp +++ b/src/hotspot/cpu/s390/downcallLinker_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -129,7 +129,7 @@ void DowncallLinker::StubGenerator::generate() { assert(!_needs_return_buffer, "unexpected needs_return_buffer"); RegSpiller out_reg_spiller(_output_registers); - int spill_offset = allocated_frame_size; + int out_spill_offset = allocated_frame_size; allocated_frame_size += BytesPerWord; StubLocations locs; @@ -153,6 +153,18 @@ void DowncallLinker::StubGenerator::generate() { GrowableArray out_regs = ForeignGlobals::replace_place_holders(_input_registers, locs); ArgumentShuffle arg_shuffle(filtered_java_regs, out_regs, _abi._scratch1); + // Need to spill for state capturing runtime call. + // The area spilled into is distinct from the capture state buffer. + RegSpiller in_reg_spiller(out_regs); + int in_spill_offset = -1; + if (_captured_state_mask != 0) { + // The spill area cannot be shared with the out_spill since + // spilling needs to happen before the call. Allocate a new + // region in the stack for this spill space. + in_spill_offset = allocated_frame_size; + allocated_frame_size += in_reg_spiller.spill_size_bytes(); + } + #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; if (lt.is_enabled()) { @@ -192,6 +204,21 @@ void DowncallLinker::StubGenerator::generate() { arg_shuffle.generate(_masm, shuffle_reg, frame::z_jit_out_preserve_size, _abi._shadow_space_bytes); __ block_comment("} argument_shuffle"); + if (_captured_state_mask != 0) { + assert(in_spill_offset != -1, "must be"); + __ block_comment("{ load initial thread local"); + in_reg_spiller.generate_spill(_masm, in_spill_offset); + + // Copy the contents of the capture state buffer into thread local + __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, DowncallLinker::capture_state_pre)); + __ z_lg(Z_ARG1, Address(Z_SP, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ load_const_optimized(Z_ARG2, _captured_state_mask); + __ call(call_target_address); + + in_reg_spiller.generate_fill(_masm, in_spill_offset); + __ block_comment("} load initial thread local"); + } + __ call(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); ////////////////////////////////////////////////////////////////////////////// @@ -199,14 +226,14 @@ void DowncallLinker::StubGenerator::generate() { if (_captured_state_mask != 0) { __ block_comment("save_thread_local {"); - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); - __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, DowncallLinker::capture_state)); + __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, DowncallLinker::capture_state_post)); __ z_lg(Z_ARG1, Address(Z_SP, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); __ load_const_optimized(Z_ARG2, _captured_state_mask); __ call(call_target_address); - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); __ block_comment("} save_thread_local"); } @@ -259,13 +286,13 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_safepoint_poll_slow_path); // Need to save the native result registers around any runtime calls. - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, JavaThread::check_special_condition_for_native_trans)); __ z_lgr(Z_ARG1, Z_thread); __ call(call_target_address); - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); __ z_bru(L_after_safepoint_poll); __ block_comment("} L_safepoint_poll_slow_path"); @@ -275,12 +302,12 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_reguard); // Need to save the native result registers around any runtime calls. - out_reg_spiller.generate_spill(_masm, spill_offset); + out_reg_spiller.generate_spill(_masm, out_spill_offset); __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, SharedRuntime::reguard_yellow_pages)); __ call(call_target_address); - out_reg_spiller.generate_fill(_masm, spill_offset); + out_reg_spiller.generate_fill(_masm, out_spill_offset); __ z_bru(L_after_reguard); diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp index c48940198ea..e3bf5f17fe9 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,10 +145,10 @@ void DowncallLinker::StubGenerator::generate() { // when we don't use a return buffer we need to spill the return value around our slow path calls bool should_save_return_value = !_needs_return_buffer; RegSpiller out_reg_spiller(_output_registers); - int spill_rsp_offset = -1; + int out_spill_rsp_offset = -1; if (should_save_return_value) { - spill_rsp_offset = 0; + out_spill_rsp_offset = 0; // spill area can be shared with shadow space and out args, // since they are only used before the call, // and spill area is only used after. @@ -173,6 +173,9 @@ void DowncallLinker::StubGenerator::generate() { // FP-> | | // |---------------------| = frame_bottom_offset = frame_size // | (optional) | + // | in_reg_spiller area | + // |---------------------| + // | (optional) | // | capture state buf | // |---------------------| = StubLocations::CAPTURED_STATE_BUFFER // | (optional) | @@ -188,6 +191,18 @@ void DowncallLinker::StubGenerator::generate() { VMStorage shuffle_reg = as_VMStorage(rbx); ArgumentShuffle arg_shuffle(filtered_java_regs, out_regs, shuffle_reg); + // Need to spill for state capturing runtime call. + // The area spilled into is distinct from the capture state buffer. + RegSpiller in_reg_spiller(out_regs); + int in_spill_rsp_offset = -1; + if (_captured_state_mask != 0) { + // The spill area cannot be shared with the shadow/out args space + // since spilling needs to happen before the call. Allocate a new + // region in the stack for this spill space. + in_spill_rsp_offset = allocated_frame_size; + allocated_frame_size += in_reg_spiller.spill_size_bytes(); + } + #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; if (lt.is_enabled()) { @@ -232,6 +247,19 @@ void DowncallLinker::StubGenerator::generate() { arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes); __ block_comment("} argument shuffle"); + if (_captured_state_mask != 0) { + assert(in_spill_rsp_offset != -1, "must be"); + __ block_comment("{ load initial thread local"); + in_reg_spiller.generate_spill(_masm, in_spill_rsp_offset); + + // Copy the contents of the capture state buffer into thread local + __ movptr(c_rarg0, Address(rsp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ movl(c_rarg1, _captured_state_mask); + runtime_call(_masm, CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_pre)); + + in_reg_spiller.generate_fill(_masm, in_spill_rsp_offset); + __ block_comment("} load initial thread local"); + } __ call(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); assert(!_abi.is_volatile_reg(r15_thread), "Call assumed not to kill r15"); @@ -258,15 +286,15 @@ void DowncallLinker::StubGenerator::generate() { __ block_comment("{ save thread local"); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_rsp_offset); + out_reg_spiller.generate_spill(_masm, out_spill_rsp_offset); } __ movptr(c_rarg0, Address(rsp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); __ movl(c_rarg1, _captured_state_mask); - runtime_call(_masm, CAST_FROM_FN_PTR(address, DowncallLinker::capture_state)); + runtime_call(_masm, CAST_FROM_FN_PTR(address, DowncallLinker::capture_state_post)); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_rsp_offset); + out_reg_spiller.generate_fill(_masm, out_spill_rsp_offset); } __ block_comment("} save thread local"); @@ -319,14 +347,14 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_safepoint_poll_slow_path); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_rsp_offset); + out_reg_spiller.generate_spill(_masm, out_spill_rsp_offset); } __ mov(c_rarg0, r15_thread); runtime_call(_masm, CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_rsp_offset); + out_reg_spiller.generate_fill(_masm, out_spill_rsp_offset); } __ jmp(L_after_safepoint_poll); @@ -338,13 +366,13 @@ void DowncallLinker::StubGenerator::generate() { __ bind(L_reguard); if (should_save_return_value) { - out_reg_spiller.generate_spill(_masm, spill_rsp_offset); + out_reg_spiller.generate_spill(_masm, out_spill_rsp_offset); } runtime_call(_masm, CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)); if (should_save_return_value) { - out_reg_spiller.generate_fill(_masm, spill_rsp_offset); + out_reg_spiller.generate_fill(_masm, out_spill_rsp_offset); } __ jmp(L_after_reguard); diff --git a/src/hotspot/share/prims/downcallLinker.cpp b/src/hotspot/share/prims/downcallLinker.cpp index 5dde825d75f..cbef9841652 100644 --- a/src/hotspot/share/prims/downcallLinker.cpp +++ b/src/hotspot/share/prims/downcallLinker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,15 +30,34 @@ #include #endif +// keep in synch with jdk.internal.foreign.abi.CapturableState +enum PreservableValues { + NONE = 0, + GET_LAST_ERROR = 1, + WSA_GET_LAST_ERROR = 1 << 1, + ERRNO = 1 << 2 +}; + +// We call this from _thread_in_native, right before a downcall +JVM_LEAF(void, DowncallLinker::capture_state_pre(int32_t* value_ptr, int captured_state_mask)) +#ifdef _WIN64 + if (captured_state_mask & GET_LAST_ERROR) { + SetLastError(*value_ptr); + } + value_ptr++; + if (captured_state_mask & WSA_GET_LAST_ERROR) { + WSASetLastError(*value_ptr); + *value_ptr = WSAGetLastError(); + } + value_ptr++; +#endif + if (captured_state_mask & ERRNO) { + errno = *value_ptr; + } +JVM_END + // We call this from _thread_in_native, right after a downcall -JVM_LEAF(void, DowncallLinker::capture_state(int32_t* value_ptr, int captured_state_mask)) - // keep in synch with jdk.internal.foreign.abi.CapturableState - enum PreservableValues { - NONE = 0, - GET_LAST_ERROR = 1, - WSA_GET_LAST_ERROR = 1 << 1, - ERRNO = 1 << 2 - }; +JVM_LEAF(void, DowncallLinker::capture_state_post(int32_t* value_ptr, int captured_state_mask)) #ifdef _WIN64 if (captured_state_mask & GET_LAST_ERROR) { *value_ptr = GetLastError(); diff --git a/src/hotspot/share/prims/downcallLinker.hpp b/src/hotspot/share/prims/downcallLinker.hpp index 01ee5c56776..2c2cf053033 100644 --- a/src/hotspot/share/prims/downcallLinker.hpp +++ b/src/hotspot/share/prims/downcallLinker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ public: int captured_state_mask, bool needs_transition); - // This is defined as JVM_LEAF which adds the JNICALL modifier. - static void JNICALL capture_state(int32_t* value_ptr, int captured_state_mask); + // These are defined as JVM_LEAF which adds the JNICALL modifier. + static void JNICALL capture_state_pre(int32_t* value_ptr, int captured_state_mask); + static void JNICALL capture_state_post(int32_t* value_ptr, int captured_state_mask); class StubGenerator : public StubCodeGenerator { BasicType* _signature; diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index cfa03090299..1a7d33266aa 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -813,25 +813,28 @@ public sealed interface Linker permits AbstractLinker { } /** - * {@return a linker option used to save portions of the execution state - * immediately after calling a foreign function associated with a - * downcall method handle, before it can be overwritten by the Java - * runtime, or read through conventional means} + * {@return a linker option used to initialize portions of the execution + * state immediately before, and save portions of the execution + * state immediately after calling a foreign function associated + * with a downcall method handle, before it can be overwritten by the + * Java runtime, or read through conventional means} *

      - * Execution state is captured by a downcall method handle on invocation, by - * writing it to a native segment provided by the user to the downcall method - * handle. For this purpose, a downcall method handle linked with this option - * will feature an additional {@link MemorySegment} parameter directly following - * the target address, and optional {@link SegmentAllocator} parameters. This - * parameter, the capture state segment, represents the native segment - * into which the captured state is written. + * Execution state is initialized from, or saved to a native segment provided by + * the user to the downcall method handle. For this purpose, a downcall method + * handle linked with this option will feature an additional {@link MemorySegment} + * parameter directly following the target address, and optional {@link SegmentAllocator} + * parameters. This parameter, the capture state segment, represents the + * native segment from which the capture state is initialized, and into which the + * capture state is saved. *

      * The capture state segment must have size and alignment compatible with the * layout returned by {@linkplain #captureStateLayout}. This layout is a struct * layout which has a named field for each captured value. *

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

      * The following example demonstrates the use of this linker option: * {@snippet lang = "java": @@ -843,6 +846,7 @@ public sealed interface Linker permits AbstractLinker { * VarHandle errnoHandle = capturedStateLayout.varHandle(PathElement.groupElement("errno")); * try (Arena arena = Arena.ofConfined()) { * MemorySegment capturedState = arena.allocate(capturedStateLayout); + * errnoHandle.set(capturedState, 0L, 0); // set errno to 0 * handle.invoke(capturedState); * int errno = (int) errnoHandle.get(capturedState, 0L); * // use errno diff --git a/src/java.base/share/native/libfallbackLinker/fallbackLinker.c b/src/java.base/share/native/libfallbackLinker/fallbackLinker.c index 3f57a2b97cf..7519efd93bb 100644 --- a/src/java.base/share/native/libfallbackLinker/fallbackLinker.c +++ b/src/java.base/share/native/libfallbackLinker/fallbackLinker.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,14 +87,32 @@ Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1get_1struct_1offsets(JNI return ffi_get_struct_offsets((ffi_abi) abi, jlong_to_ptr(type), jlong_to_ptr(offsets)); } -static void do_capture_state(int32_t* value_ptr, int captured_state_mask) { - // keep in synch with jdk.internal.foreign.abi.CapturableState - enum PreservableValues { - NONE = 0, - GET_LAST_ERROR = 1, - WSA_GET_LAST_ERROR = 1 << 1, - ERRNO = 1 << 2 - }; +// keep in synch with jdk.internal.foreign.abi.CapturableState +enum PreservableValues { + NONE = 0, + GET_LAST_ERROR = 1, + WSA_GET_LAST_ERROR = 1 << 1, + ERRNO = 1 << 2 +}; + +static void do_capture_state_pre(int32_t* value_ptr, int captured_state_mask) { +#ifdef _WIN64 + if (captured_state_mask & GET_LAST_ERROR) { + SetLastError(*value_ptr); + } + value_ptr++; + if (captured_state_mask & WSA_GET_LAST_ERROR) { + WSASetLastError(*value_ptr); + *value_ptr = WSAGetLastError(); + } + value_ptr++; +#endif + if (captured_state_mask & ERRNO) { + errno = *value_ptr; + } +} + +static void do_capture_state_post(int32_t* value_ptr, int captured_state_mask) { #ifdef _WIN64 if (captured_state_mask & GET_LAST_ERROR) { *value_ptr = GetLastError(); @@ -142,10 +160,15 @@ Java_jdk_internal_foreign_abi_fallback_LibFallback_doDowncall(JNIEnv* env, jclas } } + if (captured_state_mask != 0) { + // Copy the contents of the capture state buffer into thread local + do_capture_state_pre(captured_state_addr, captured_state_mask); + } + ffi_call(jlong_to_ptr(cif), jlong_to_ptr(fn), jlong_to_ptr(rvalue), jlong_to_ptr(avalues)); if (captured_state_mask != 0) { - do_capture_state(captured_state_addr, captured_state_mask); + do_capture_state_post(captured_state_addr, captured_state_mask); } if (heapBases != NULL) { diff --git a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java index 2c69c5691b8..8ef5483bd82 100644 --- a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java +++ b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,7 +73,7 @@ public class TestCaptureCallState extends NativeTestHelper { } private record SaveValuesCase(String nativeTarget, FunctionDescriptor nativeDesc, String threadLocalName, - Consumer resultCheck, boolean critical) {} + Consumer resultCheck, boolean expectTestValue, boolean critical) {} @Test(dataProvider = "cases") public void testSavedThreadLocal(SaveValuesCase testCase) throws Throwable { @@ -90,14 +90,21 @@ public class TestCaptureCallState extends NativeTestHelper { try (Arena arena = Arena.ofConfined()) { MemorySegment saveSeg = arena.allocate(capturedStateLayout); + // The existing value and the value that it should be overwritten with + int prevValue = 24; int testValue = 42; + errnoHandle.set(saveSeg, 0L, prevValue); boolean needsAllocator = testCase.nativeDesc().returnLayout().map(StructLayout.class::isInstance).orElse(false); Object result = needsAllocator ? handle.invoke(arena, saveSeg, testValue) : handle.invoke(saveSeg, testValue); testCase.resultCheck().accept(result); int savedErrno = (int) errnoHandle.get(saveSeg, 0L); - assertEquals(savedErrno, testValue); + if (testCase.expectTestValue()) { + assertEquals(savedErrno, testValue); + } else { + assertEquals(savedErrno, prevValue); + } } } @@ -127,37 +134,45 @@ public class TestCaptureCallState extends NativeTestHelper { for (boolean critical : new boolean[]{ true, false }) { cases.add(new SaveValuesCase("set_errno_V", FunctionDescriptor.ofVoid(JAVA_INT), - "errno", o -> {}, critical)); + "errno", o -> {}, true, critical)); + cases.add(new SaveValuesCase("noset_errno_V", FunctionDescriptor.ofVoid(JAVA_INT), + "errno", o -> {}, false, critical)); cases.add(new SaveValuesCase("set_errno_I", FunctionDescriptor.of(JAVA_INT, JAVA_INT), - "errno", o -> assertEquals((int) o, 42), critical)); + "errno", o -> assertEquals((int) o, 42), true, critical)); cases.add(new SaveValuesCase("set_errno_D", FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT), - "errno", o -> assertEquals((double) o, 42.0), critical)); + "errno", o -> assertEquals((double) o, 42.0), true, critical)); - cases.add(structCase("SL", Map.of(JAVA_LONG.withName("x"), 42L), critical)); + cases.add(structCase("SL", Map.of(JAVA_LONG.withName("x"), 42L), true, critical)); cases.add(structCase("SLL", Map.of(JAVA_LONG.withName("x"), 42L, - JAVA_LONG.withName("y"), 42L), critical)); + JAVA_LONG.withName("y"), 42L), true, critical)); cases.add(structCase("SLLL", Map.of(JAVA_LONG.withName("x"), 42L, JAVA_LONG.withName("y"), 42L, - JAVA_LONG.withName("z"), 42L), critical)); - cases.add(structCase("SD", Map.of(JAVA_DOUBLE.withName("x"), 42D), critical)); + JAVA_LONG.withName("z"), 42L), true, critical)); + cases.add(structCase("SLLL", Map.of(JAVA_LONG.withName("x"), 42L, + JAVA_LONG.withName("y"), 42L, + JAVA_LONG.withName("z"), 42L), false, critical)); + cases.add(structCase("SD", Map.of(JAVA_DOUBLE.withName("x"), 42D), true, critical)); cases.add(structCase("SDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, - JAVA_DOUBLE.withName("y"), 42D), critical)); + JAVA_DOUBLE.withName("y"), 42D), true, critical)); cases.add(structCase("SDDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, JAVA_DOUBLE.withName("y"), 42D, - JAVA_DOUBLE.withName("z"), 42D), critical)); + JAVA_DOUBLE.withName("z"), 42D), true, critical)); if (IS_WINDOWS) { cases.add(new SaveValuesCase("SetLastError", FunctionDescriptor.ofVoid(JAVA_INT), - "GetLastError", o -> {}, critical)); + "GetLastError", o -> {}, true, critical)); cases.add(new SaveValuesCase("WSASetLastError", FunctionDescriptor.ofVoid(JAVA_INT), - "WSAGetLastError", o -> {}, critical)); + "WSAGetLastError", o -> {}, true, critical)); } } return cases.stream().map(tc -> new Object[] {tc}).toArray(Object[][]::new); } - static SaveValuesCase structCase(String name, Map fields, boolean critical) { + static SaveValuesCase structCase(String name, + Map fields, + boolean expectTestValue, + boolean critical) { StructLayout layout = MemoryLayout.structLayout(fields.keySet().toArray(MemoryLayout[]::new)); Consumer check = o -> {}; @@ -167,9 +182,9 @@ public class TestCaptureCallState extends NativeTestHelper { Object value = field.getValue(); check = check.andThen(o -> assertEquals(fieldHandle.get(o, 0L), value)); } - - return new SaveValuesCase("set_errno_" + name, FunctionDescriptor.of(layout, JAVA_INT), - "errno", check, critical); + String prefix = expectTestValue ? "set_errno_" : "noset_errno_"; + return new SaveValuesCase(prefix + name, FunctionDescriptor.of(layout, JAVA_INT), + "errno", check, expectTestValue, critical); } @DataProvider diff --git a/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c b/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c index d76c9d7beda..fe0d144cb5b 100644 --- a/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c +++ b/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,10 @@ EXPORT void set_errno_V(int value) { errno = value; } +EXPORT int noset_errno_V(int value) { + return 42; +} + EXPORT int set_errno_I(int value) { errno = value; return 42; @@ -78,6 +82,14 @@ EXPORT struct SLLL set_errno_SLLL(int value) { return s; } +EXPORT struct SLLL noset_errno_SLLL(int value) { + struct SLLL s; + s.x = 42; + s.y = 42; + s.z = 42; + return s; +} + struct SD { double x; }; From 256512147d4ecabfddf29f8391640743d63ebc21 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 11 Mar 2026 09:29:29 +0000 Subject: [PATCH 167/170] 8379448: [PPC64] Build without C2 broken after 8373595 Reviewed-by: rrich, aboldtch, mbaesken, dbriemann --- .../ppc/gc/shared/barrierSetAssembler_ppc.cpp | 12 ++++---- .../ppc/gc/shared/barrierSetAssembler_ppc.hpp | 10 +++++-- .../shenandoahBarrierSetAssembler_ppc.cpp | 14 ++++------ .../shenandoahBarrierSetAssembler_ppc.hpp | 7 ++--- .../cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp | 28 +++++++++---------- .../cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp | 6 ++-- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 4 +-- 7 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp index 82d06f6c685..3692b247989 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, 2025 SAP SE. All rights reserved. + * Copyright (c) 2018, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -179,6 +179,11 @@ void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Re __ ld(dst, 0, dst); // Resolve (untagged) jobject. } +void BarrierSetAssembler::try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { + // Load the oop from the weak handle. + __ ld(obj, 0, obj); +} + void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register tmp) { BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); assert_different_registers(tmp, R0); @@ -275,11 +280,6 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na return opto_reg; } -void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Load the oop from the weak handle. - __ ld(obj, 0, obj); -} - #undef __ #define __ _masm-> diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp index d78071f2ee0..8112542d761 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018, 2022 SAP SE. All rights reserved. + * Copyright (c) 2018, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,6 +70,12 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, Register obj, Register tmp, Label& slowpath); + // Can be used in nmethods including native wrappers. + // Attention: obj will only be valid until next safepoint (no SATB barrier). + // TODO: maybe rename to try_peek_weak_handle on all platforms (try: operation may fail, peek: obj is not kept alive) + // (other platforms currently use it for C2 only: try_resolve_weak_handle_in_c2) + virtual void try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); + virtual void barrier_stubs_init() {} virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::stw_instruction_and_data_patch; } @@ -81,8 +87,6 @@ public: #ifdef COMPILER2 OptoReg::Name refine_register(const Node* node, OptoReg::Name opto_reg) const; - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, - Register tmp, Label& slow_path); #endif // COMPILER2 }; diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index e1f0416d65d..8e99d23cc99 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2025, Red Hat, Inc. All rights reserved. - * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -663,17 +663,16 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler __ block_comment("} try_resolve_jobject_in_native (shenandoahgc)"); } -#ifdef COMPILER2 -void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler *masm, Register obj, - Register tmp, Label &slow_path) { - __ block_comment("try_resolve_weak_handle_in_c2 (shenandoahgc) {"); +void ShenandoahBarrierSetAssembler::try_resolve_weak_handle(MacroAssembler *masm, Register obj, + Register tmp, Label &slow_path) { + __ block_comment("try_resolve_weak_handle (shenandoahgc) {"); assert_different_registers(obj, tmp); Label done; // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path); + BarrierSetAssembler::try_resolve_weak_handle(masm, obj, tmp, slow_path); // Check if the reference is null, and if it is, take the fast path. __ cmpdi(CR0, obj, 0); @@ -686,9 +685,8 @@ void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler __ bne(CR0, slow_path); __ bind(done); - __ block_comment("} try_resolve_weak_handle_in_c2 (shenandoahgc)"); + __ block_comment("} try_resolve_weak_handle (shenandoahgc)"); } -#endif // Special shenandoah CAS implementation that handles false negatives due // to concurrent evacuation. That is, the CAS operation is intended to succeed in diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp index 672f8122bcb..58180c49642 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2022, Red Hat, Inc. All rights reserved. - * Copyright (c) 2012, 2022 SAP SE. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,9 +122,8 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, Register obj, Register tmp, Label& slowpath); -#ifdef COMPILER2 - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); -#endif + + virtual void try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); }; #endif // CPU_PPC_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_PPC_HPP diff --git a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp index bfa3c87c179..3e74dfb88cb 100644 --- a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2025 SAP SE. All rights reserved. + * Copyright (c) 2021, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -627,6 +627,19 @@ void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, R __ block_comment("} try_resolve_jobject_in_native (zgc)"); } +void ZBarrierSetAssembler::try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { + // Resolve weak handle using the standard implementation. + BarrierSetAssembler::try_resolve_weak_handle(masm, obj, tmp, slow_path); + + // Check if the oop is bad, in which case we need to take the slow path. + __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatMarkBadMask); + __ andi_(R0, obj, barrier_Relocation::unpatched); + __ bne(CR0, slow_path); + + // Oop is okay, so we uncolor it. + __ srdi(obj, obj, ZPointerLoadShift); +} + #undef __ #ifdef COMPILER1 @@ -950,19 +963,6 @@ void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, __ b(*stub->continuation()); } -void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path); - - // Check if the oop is bad, in which case we need to take the slow path. - __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatMarkBadMask); - __ andi_(R0, obj, barrier_Relocation::unpatched); - __ bne(CR0, slow_path); - - // Oop is okay, so we uncolor it. - __ srdi(obj, obj, ZPointerLoadShift); -} - #undef __ #endif // COMPILER2 diff --git a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp index e31817370d9..655184cf6a3 100644 --- a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021, 2022 SAP SE. All rights reserved. + * Copyright (c) 2021, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,8 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, Register obj, Register tmp, Label& slowpath); + virtual void try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); + virtual void check_oop(MacroAssembler *masm, Register obj, const char* msg); virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_instruction_and_data_patch; } @@ -108,8 +110,6 @@ public: void generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const; void generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const; - - void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); #endif // COMPILER2 void store_barrier_fast(MacroAssembler* masm, diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 986dd335816..f3050cbabb4 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2025 SAP SE. All rights reserved. + * Copyright (c) 2012, 2026 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2800,7 +2800,7 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register // Check if object matches. ld(tmp3, in_bytes(ObjectMonitor::object_offset()), monitor); BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->try_resolve_weak_handle_in_c2(this, tmp3, tmp2, slow_path); + bs_asm->try_resolve_weak_handle(this, tmp3, tmp2, slow_path); cmpd(CR0, tmp3, obj); bne(CR0, slow_path); From acbd1febdd8662f857a0ff140e85d59ce80f6d6a Mon Sep 17 00:00:00 2001 From: Leo Korinth Date: Wed, 11 Mar 2026 10:12:37 +0000 Subject: [PATCH 168/170] 8377658: Cleanup files for enabling conversion warnings for g1ConcurrentMark.cpp Reviewed-by: stefank, tschatzl, jsjolen --- .../share/gc/g1/g1ConcurrentMarkThread.inline.hpp | 4 ++-- src/hotspot/share/gc/g1/g1RegionMarkStatsCache.hpp | 2 +- src/hotspot/share/oops/bsmAttribute.hpp | 12 ++++++------ src/hotspot/share/oops/bsmAttribute.inline.hpp | 4 ++-- src/hotspot/share/oops/compressedKlass.hpp | 4 ++-- src/hotspot/share/oops/constantPool.hpp | 6 +++--- src/hotspot/share/oops/fieldInfo.hpp | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp index 254eaf62bb2..e80c5023405 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ // Total virtual time so far. inline double G1ConcurrentMarkThread::total_mark_cpu_time_s() { - return os::thread_cpu_time(this) + worker_threads_cpu_time_s(); + return static_cast(os::thread_cpu_time(this)) + worker_threads_cpu_time_s(); } // Marking virtual time so far diff --git a/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.hpp b/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.hpp index 4dcdd33846e..df76147f4b1 100644 --- a/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.hpp +++ b/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.hpp @@ -95,7 +95,7 @@ private: // Evict a given element of the statistics cache. void evict(uint idx); - size_t _num_cache_entries_mask; + const uint _num_cache_entries_mask; uint hash(uint idx) { return idx & _num_cache_entries_mask; diff --git a/src/hotspot/share/oops/bsmAttribute.hpp b/src/hotspot/share/oops/bsmAttribute.hpp index a28d2757fb0..32bc58b5b07 100644 --- a/src/hotspot/share/oops/bsmAttribute.hpp +++ b/src/hotspot/share/oops/bsmAttribute.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,18 +61,18 @@ public: _argv_offset = 2 }; - int bootstrap_method_index() const { + u2 bootstrap_method_index() const { return _bootstrap_method_index; } - int argument_count() const { + u2 argument_count() const { return _argument_count; } - int argument(int n) const { - assert(checked_cast(n) < _argument_count, "oob"); + u2 argument(u2 n) const { + assert(n < _argument_count, "oob"); return argument_indexes()[n]; } - void set_argument(int index, u2 value) { + void set_argument(u2 index, u2 value) { assert(index >= 0 && index < argument_count(), "invariant"); argument_indexes()[index] = value; } diff --git a/src/hotspot/share/oops/bsmAttribute.inline.hpp b/src/hotspot/share/oops/bsmAttribute.inline.hpp index e678c280c26..8e048704e08 100644 --- a/src/hotspot/share/oops/bsmAttribute.inline.hpp +++ b/src/hotspot/share/oops/bsmAttribute.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ inline BSMAttributeEntry* BSMAttributeEntries::InsertionIterator::reserve_new_en inline void BSMAttributeEntry::copy_args_into(BSMAttributeEntry* entry) const { assert(entry->argument_count() == this->argument_count(), "must be same"); - for (int i = 0; i < argument_count(); i++) { + for (u2 i = 0; i < argument_count(); i++) { entry->set_argument(i, this->argument(i)); } } diff --git a/src/hotspot/share/oops/compressedKlass.hpp b/src/hotspot/share/oops/compressedKlass.hpp index 64b9fcf9c82..98a9eafdbf4 100644 --- a/src/hotspot/share/oops/compressedKlass.hpp +++ b/src/hotspot/share/oops/compressedKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,7 +231,7 @@ public: // Returns the alignment a Klass* is guaranteed to have. // Note: *Not* the same as 1 << shift ! Klass are always guaranteed to be at least 64-bit aligned, // so this will return 8 even if shift is 0. - static int klass_alignment_in_bytes() { return nth_bit(MAX2(3, _shift)); } + static int klass_alignment_in_bytes() { return static_cast(nth_bit(MAX2(3, _shift))); } static int klass_alignment_in_words() { return klass_alignment_in_bytes() / BytesPerWord; } // Returns the highest possible narrowKlass value given the current Klass range diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index 6c519945f4d..b4cff2bbbe6 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -554,8 +554,8 @@ class ConstantPool : public Metadata { u2 bootstrap_argument_index_at(int cp_index, int j) { int bsmai = bootstrap_methods_attribute_index(cp_index); BSMAttributeEntry* bsme = bsm_attribute_entry(bsmai); - assert((uint)j < (uint)bsme->argument_count(), "oob"); - return bsm_attribute_entry(bsmai)->argument(j); + assert(j < bsme->argument_count(), "oob"); + return bsm_attribute_entry(bsmai)->argument(checked_cast(j)); } // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, diff --git a/src/hotspot/share/oops/fieldInfo.hpp b/src/hotspot/share/oops/fieldInfo.hpp index b6d9c4d34e5..88c982e9d1f 100644 --- a/src/hotspot/share/oops/fieldInfo.hpp +++ b/src/hotspot/share/oops/fieldInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -302,7 +302,7 @@ class FieldStatus { // boilerplate: u1 _flags; - static constexpr u1 flag_mask(FieldStatusBitPosition pos) { return (u1)1 << (int)pos; } + static constexpr u1 flag_mask(FieldStatusBitPosition pos) { return checked_cast(1 << pos); } bool test_flag(FieldStatusBitPosition pos) { return (_flags & flag_mask(pos)) != 0; } // this performs an atomic update on a live status byte! void update_flag(FieldStatusBitPosition pos, bool z); From c904a0edae3d1807d4c6f13e41d5186caae71187 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 11 Mar 2026 11:14:59 +0000 Subject: [PATCH 169/170] 8378338: Shenandoah: Heap-used generic verification error after update-refs Reviewed-by: wkemper --- src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 225339a3219..afef11640c9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -1086,7 +1086,7 @@ void ShenandoahVerifier::verify_generic(ShenandoahGeneration* generation, Verify _verify_cset_disable, // cset may be inconsistent _verify_liveness_disable, // no reliable liveness data _verify_regions_disable, // no reliable region data - _verify_size_exact, // expect generation and heap sizes to match exactly + _verify_size_disable, // no reliable sizing data _verify_gcstate_disable // no data about gcstate ); } From 97f9060abec87a201a2858bde06595f500c871b6 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Wed, 11 Mar 2026 13:24:20 +0000 Subject: [PATCH 170/170] 8379181: Convert ObjectMonitorTable to use Atomic Reviewed-by: kbarrett, tschatzl --- .../share/runtime/objectMonitorTable.cpp | 111 +++++++++--------- .../share/runtime/objectMonitorTable.hpp | 3 +- 2 files changed, 60 insertions(+), 54 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitorTable.cpp b/src/hotspot/share/runtime/objectMonitorTable.cpp index 8431b6dd0d4..1b79d1bf1c4 100644 --- a/src/hotspot/share/runtime/objectMonitorTable.cpp +++ b/src/hotspot/share/runtime/objectMonitorTable.cpp @@ -31,6 +31,7 @@ #include "runtime/thread.hpp" #include "runtime/timerTrace.hpp" #include "runtime/trimNativeHeap.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" // ----------------------------------------------------------------------------- @@ -117,17 +118,17 @@ // requirements. Don't change it for fun, it might backfire. // ----------------------------------------------------------------------------- -ObjectMonitorTable::Table* volatile ObjectMonitorTable::_curr; +Atomic ObjectMonitorTable::_curr; class ObjectMonitorTable::Table : public CHeapObj { friend class ObjectMonitorTable; DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); const size_t _capacity_mask; // One less than its power-of-two capacity - Table* volatile _prev; // Set while rehashing - Entry volatile* _buckets; // The payload + Atomic _prev; // Set while rehashing + Atomic* _buckets; // The payload DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(_capacity_mask) + sizeof(_prev) + sizeof(_buckets)); - volatile size_t _items_count; + Atomic _items_count; DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(_items_count)); static Entry as_entry(ObjectMonitor* monitor) { @@ -156,11 +157,11 @@ class ObjectMonitorTable::Table : public CHeapObj { // Make sure we leave space for previous versions to relocate too. bool try_inc_items_count() { for (;;) { - size_t population = AtomicAccess::load(&_items_count); + size_t population = _items_count.load_relaxed(); if (should_grow(population)) { return false; } - if (AtomicAccess::cmpxchg(&_items_count, population, population + 1, memory_order_relaxed) == population) { + if (_items_count.compare_set(population, population + 1, memory_order_relaxed)) { return true; } } @@ -171,31 +172,31 @@ class ObjectMonitorTable::Table : public CHeapObj { } void inc_items_count() { - AtomicAccess::inc(&_items_count, memory_order_relaxed); + _items_count.add_then_fetch(1u, memory_order_relaxed); } void dec_items_count() { - AtomicAccess::dec(&_items_count, memory_order_relaxed); + _items_count.sub_then_fetch(1u, memory_order_relaxed); } public: Table(size_t capacity, Table* prev) : _capacity_mask(capacity - 1), _prev(prev), - _buckets(NEW_C_HEAP_ARRAY(Entry, capacity, mtObjectMonitor)), + _buckets(NEW_C_HEAP_ARRAY(Atomic, capacity, mtObjectMonitor)), _items_count(0) { for (size_t i = 0; i < capacity; ++i) { - _buckets[i] = empty(); + ::new (_buckets + i) Atomic(empty()); } } ~Table() { - FREE_C_HEAP_ARRAY(Entry, _buckets); + FREE_C_HEAP_ARRAY(Atomic, _buckets); } Table* prev() { - return AtomicAccess::load(&_prev); + return _prev.load_relaxed(); } size_t capacity() { @@ -207,12 +208,12 @@ public: } bool should_grow() { - return should_grow(AtomicAccess::load(&_items_count)); + return should_grow(_items_count.load_relaxed()); } size_t total_items() { - size_t current_items = AtomicAccess::load(&_items_count); - Table* prev = AtomicAccess::load(&_prev); + size_t current_items = _items_count.load_relaxed(); + Table* prev = _prev.load_relaxed(); if (prev != nullptr) { return prev->total_items() + current_items; } @@ -221,7 +222,7 @@ public: ObjectMonitor* get(oop obj, intptr_t hash) { // Acquire tombstones and relocations in case prev transitioned to null - Table* prev = AtomicAccess::load_acquire(&_prev); + Table* prev = _prev.load_acquire(); if (prev != nullptr) { ObjectMonitor* result = prev->get(obj, hash); if (result != nullptr) { @@ -233,8 +234,8 @@ public: size_t index = start_index; for (;;) { - Entry volatile* bucket = _buckets + index; - Entry entry = AtomicAccess::load_acquire(bucket); + Atomic& bucket = _buckets[index]; + Entry entry = bucket.load_acquire(); if (entry == tombstone() || entry == empty()) { // Not found @@ -257,7 +258,7 @@ public: ObjectMonitor* prepare_insert(oop obj, intptr_t hash) { // Acquire any tombstones and relocations if prev transitioned to null. - Table* prev = AtomicAccess::load_acquire(&_prev); + Table* prev = _prev.load_acquire(); if (prev != nullptr) { ObjectMonitor* result = prev->prepare_insert(obj, hash); if (result != nullptr) { @@ -269,13 +270,13 @@ public: size_t index = start_index; for (;;) { - Entry volatile* bucket = _buckets + index; - Entry entry = AtomicAccess::load_acquire(bucket); + Atomic& bucket = _buckets[index]; + Entry entry = bucket.load_acquire(); if (entry == empty()) { // Found an empty slot to install the new monitor in. // To avoid concurrent inserts succeeding, place a tombstone here. - Entry result = AtomicAccess::cmpxchg(bucket, entry, tombstone(), memory_order_relaxed); + Entry result = bucket.compare_exchange(entry, tombstone(), memory_order_relaxed); if (result == entry) { // Success! Nobody will try to insert here again, except reinsert from rehashing. return nullptr; @@ -300,7 +301,7 @@ public: ObjectMonitor* get_set(oop obj, Entry new_monitor, intptr_t hash) { // Acquire any tombstones and relocations if prev transitioned to null. - Table* prev = AtomicAccess::load_acquire(&_prev); + Table* prev = _prev.load_acquire(); if (prev != nullptr) { // Sprinkle tombstones in previous tables to force concurrent inserters // to the latest table. We only really want to try inserting in the @@ -315,14 +316,14 @@ public: size_t index = start_index; for (;;) { - Entry volatile* bucket = _buckets + index; - Entry entry = AtomicAccess::load_acquire(bucket); + Atomic& bucket = _buckets[index]; + Entry entry = bucket.load_acquire(); if (entry == empty()) { // Empty slot to install the new monitor if (try_inc_items_count()) { // Succeeding in claiming an item. - Entry result = AtomicAccess::cmpxchg(bucket, entry, new_monitor, memory_order_acq_rel); + Entry result = bucket.compare_exchange(entry, new_monitor, memory_order_acq_rel); if (result == entry) { // Success - already incremented. return as_monitor(new_monitor); @@ -334,7 +335,7 @@ public: } else { // Out of allowance; leaving place for rehashing to succeed. // To avoid concurrent inserts succeeding, place a tombstone here. - Entry result = AtomicAccess::cmpxchg(bucket, entry, tombstone(), memory_order_acq_rel); + Entry result = bucket.compare_exchange(entry, tombstone(), memory_order_acq_rel); if (result == entry) { // Success; nobody will try to insert here again, except reinsert from rehashing. return nullptr; @@ -366,8 +367,8 @@ public: size_t index = start_index; for (;;) { - Entry volatile* bucket = _buckets + index; - Entry entry = AtomicAccess::load_acquire(bucket); + Atomic& bucket = _buckets[index]; + Entry entry = bucket.load_acquire(); if (entry == empty()) { // The monitor does not exist in this table. @@ -381,8 +382,8 @@ public: if (entry == old_monitor) { // Found matching entry; remove it - Entry result = AtomicAccess::cmpxchg(bucket, entry, removed(), memory_order_relaxed); - assert(result == entry, "should not fail"); + bool result = bucket.compare_set(entry, removed(), memory_order_relaxed); + assert(result, "should not fail"); break; } @@ -395,8 +396,8 @@ public: // still not being a monitor, instead of flickering back to being there. // Only the deflation thread rebuilds and unlinks tables, so we do not need // any concurrency safe prev read below. - if (_prev != nullptr) { - _prev->remove(obj, old_monitor, hash); + if (_prev.load_relaxed() != nullptr) { + _prev.load_relaxed()->remove(obj, old_monitor, hash); } } @@ -407,12 +408,12 @@ public: size_t index = start_index; for (;;) { - Entry volatile* bucket = _buckets + index; - Entry entry = AtomicAccess::load_acquire(bucket); + Atomic& bucket = _buckets[index]; + Entry entry = bucket.load_acquire(); if (entry == empty()) { // Empty slot to install the new monitor. - Entry result = AtomicAccess::cmpxchg(bucket, entry, new_monitor, memory_order_acq_rel); + Entry result = bucket.compare_exchange(entry, new_monitor, memory_order_acq_rel); if (result == entry) { // Success - unconditionally increment. inc_items_count(); @@ -426,7 +427,7 @@ public: if (entry == tombstone()) { // A concurrent inserter did not get enough allowance in the table. // But reinsert always succeeds - we will take the spot. - Entry result = AtomicAccess::cmpxchg(bucket, entry, new_monitor, memory_order_acq_rel); + Entry result = bucket.compare_exchange(entry, new_monitor, memory_order_acq_rel); if (result == entry) { // Success - unconditionally increment. inc_items_count(); @@ -439,7 +440,7 @@ public: if (entry == removed()) { // A removed entry can be flipped back with reinsertion. - Entry result = AtomicAccess::cmpxchg(bucket, entry, new_monitor, memory_order_release); + Entry result = bucket.compare_exchange(entry, new_monitor, memory_order_release); if (result == entry) { // Success - but don't increment; the initial entry did that for us. return; @@ -459,7 +460,7 @@ public: } void rebuild() { - Table* prev = _prev; + Table* prev = _prev.load_relaxed(); if (prev == nullptr) { // Base case for recursion - no previous version. return; @@ -477,12 +478,12 @@ public: ThreadBlockInVM tbivm(current); } - Entry volatile* bucket = prev->_buckets + index; - Entry entry = AtomicAccess::load_acquire(bucket); + Atomic& bucket = prev->_buckets[index]; + Entry entry = bucket.load_acquire(); if (entry == empty()) { // Empty slot; put a tombstone there. - Entry result = AtomicAccess::cmpxchg(bucket, entry, tombstone(), memory_order_acq_rel); + Entry result = bucket.compare_exchange(entry, tombstone(), memory_order_acq_rel); if (result == empty()) { // Success; move to next entry. continue; @@ -508,17 +509,17 @@ public: } // Unlink this table, releasing the tombstones and relocations. - AtomicAccess::release_store(&_prev, (Table*)nullptr); + _prev.release_store(nullptr); } }; void ObjectMonitorTable::create() { - _curr = new Table(128, nullptr); + _curr.store_relaxed(new Table(128, nullptr)); } ObjectMonitor* ObjectMonitorTable::monitor_get(oop obj) { const intptr_t hash = obj->mark().hash(); - Table* curr = AtomicAccess::load_acquire(&_curr); + Table* curr = _curr.load_acquire(); ObjectMonitor* monitor = curr->get(obj, hash); return monitor; } @@ -526,7 +527,7 @@ ObjectMonitor* ObjectMonitorTable::monitor_get(oop obj) { // Returns a new table to try inserting into. ObjectMonitorTable::Table* ObjectMonitorTable::grow_table(Table* curr) { Table* result; - Table* new_table = AtomicAccess::load_acquire(&_curr); + Table* new_table = _curr.load_acquire(); if (new_table != curr) { // Table changed; no need to try further return new_table; @@ -537,14 +538,14 @@ ObjectMonitorTable::Table* ObjectMonitorTable::grow_table(Table* curr) { // attempt to allocate the new table. MonitorLocker ml(MonitorDeflation_lock, Mutex::_no_safepoint_check_flag); - new_table = AtomicAccess::load_acquire(&_curr); + new_table = _curr.load_acquire(); if (new_table != curr) { // Table changed; no need to try further return new_table; } new_table = new Table(curr->capacity() << 1, curr); - result = AtomicAccess::cmpxchg(&_curr, curr, new_table, memory_order_acq_rel); + result = _curr.compare_exchange(curr, new_table, memory_order_acq_rel); if (result == curr) { log_info(monitorinflation)("Growing object monitor table (capacity: %zu)", new_table->capacity()); @@ -565,7 +566,7 @@ ObjectMonitorTable::Table* ObjectMonitorTable::grow_table(Table* curr) { ObjectMonitor* ObjectMonitorTable::monitor_put_get(ObjectMonitor* monitor, oop obj) { const intptr_t hash = obj->mark().hash(); - Table* curr = AtomicAccess::load_acquire(&_curr); + Table* curr = _curr.load_acquire(); for (;;) { // Curr is the latest table and is reasonably loaded. @@ -585,7 +586,7 @@ void ObjectMonitorTable::remove_monitor_entry(ObjectMonitor* monitor) { return; } const intptr_t hash = obj->mark().hash(); - Table* curr = AtomicAccess::load_acquire(&_curr); + Table* curr = _curr.load_acquire(); curr->remove(obj, curr->as_entry(monitor), hash); assert(monitor_get(obj) != monitor, "should have been removed"); } @@ -620,13 +621,13 @@ void ObjectMonitorTable::rebuild(GrowableArray* delete_list) { // given the growing threshold of 12.5%, it is impossible for the // tables to reach a load factor above 50%. Which is more than // enough to guarantee the function of this concurrent hash table. - Table* curr = AtomicAccess::load_acquire(&_curr); + Table* curr = _curr.load_acquire(); size_t need_to_accomodate = curr->total_items(); size_t new_capacity = curr->should_grow(need_to_accomodate) ? curr->capacity() << 1 : curr->capacity(); new_table = new Table(new_capacity, curr); - Table* result = AtomicAccess::cmpxchg(&_curr, curr, new_table, memory_order_acq_rel); + Table* result = _curr.compare_exchange(curr, new_table, memory_order_acq_rel); if (result != curr) { // Somebody else racingly started rehashing. Delete the // new_table and treat somebody else's table as the new one. @@ -653,7 +654,7 @@ void ObjectMonitorTable::destroy(GrowableArray* delete_list) { } address ObjectMonitorTable::current_table_address() { - return (address)(&_curr); + return reinterpret_cast
      (&_curr) + _curr.value_offset_in_bytes(); } ByteSize ObjectMonitorTable::table_capacity_mask_offset() { @@ -661,5 +662,9 @@ ByteSize ObjectMonitorTable::table_capacity_mask_offset() { } ByteSize ObjectMonitorTable::table_buckets_offset() { + // Assumptions made from the emitted code about the layout. + STATIC_ASSERT(sizeof(Atomic) == sizeof(Entry*)); + STATIC_ASSERT(Atomic::value_offset_in_bytes() == 0); + return byte_offset_of(Table, _buckets); } diff --git a/src/hotspot/share/runtime/objectMonitorTable.hpp b/src/hotspot/share/runtime/objectMonitorTable.hpp index 0a56b696069..1ec372883b2 100644 --- a/src/hotspot/share/runtime/objectMonitorTable.hpp +++ b/src/hotspot/share/runtime/objectMonitorTable.hpp @@ -27,6 +27,7 @@ #include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" +#include "runtime/atomic.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/sizes.hpp" @@ -44,7 +45,7 @@ public: class Table; private: - static Table* volatile _curr; + static Atomic _curr; static Table* grow_table(Table* curr); enum class Entry : uintptr_t {