From 77dc89115e2a8de5fc600874d82cd3a75cd3b4fb Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 12 Oct 2023 08:54:32 +0000 Subject: [PATCH 001/111] 8317963: Serial: Remove unused GenerationIsInReservedClosure Reviewed-by: kbarrett, tschatzl --- src/hotspot/share/gc/serial/generation.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/hotspot/share/gc/serial/generation.cpp b/src/hotspot/share/gc/serial/generation.cpp index 32f70f08c65..1e9f4959ffb 100644 --- a/src/hotspot/share/gc/serial/generation.cpp +++ b/src/hotspot/share/gc/serial/generation.cpp @@ -94,18 +94,6 @@ void Generation::print_summary_info_on(outputStream* st) { // Utility iterator classes -class GenerationIsInReservedClosure : public SpaceClosure { - public: - const void* _p; - Space* sp; - virtual void do_space(Space* s) { - if (sp == nullptr) { - if (s->is_in_reserved(_p)) sp = s; - } - } - GenerationIsInReservedClosure(const void* p) : _p(p), sp(nullptr) {} -}; - class GenerationIsInClosure : public SpaceClosure { public: const void* _p; From 00ef9f9c322dde236256953272d6906f6151635d Mon Sep 17 00:00:00 2001 From: Ravi Gupta Date: Thu, 12 Oct 2023 09:40:02 +0000 Subject: [PATCH 002/111] 8316947: Write a test to check textArea triggers MouseEntered/MouseExited events properly Reviewed-by: tr, honkar, aivanov --- .../event/MouseEvent/MouseEnterExitTest.java | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 test/jdk/java/awt/event/MouseEvent/MouseEnterExitTest.java diff --git a/test/jdk/java/awt/event/MouseEvent/MouseEnterExitTest.java b/test/jdk/java/awt/event/MouseEvent/MouseEnterExitTest.java new file mode 100644 index 00000000000..67c02722a37 --- /dev/null +++ b/test/jdk/java/awt/event/MouseEvent/MouseEnterExitTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +/* + * @test + * @key headful + * @bug 4454304 + * @summary On Solaris, TextArea triggers MouseEntered when the mouse is inside the component + * @run main MouseEnterExitTest + */ +public class MouseEnterExitTest { + + private static Frame frame; + + private volatile static boolean entered = false; + private volatile static boolean exited = false; + private volatile static boolean passed = true; + + private volatile static Point compAt; + private volatile static Dimension compSize; + + private static final MouseListener mouseListener = new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + System.out.println( + "MouseEntered component " + e.getSource().getClass().getName()); + if (entered) { + passed = false; + } + entered = true; + exited = false; + } + + @Override + public void mouseExited(MouseEvent e) { + System.out.println( + "MouseExited component " + e.getSource().getClass().getName()); + if (exited) { + passed = false; + } + entered = false; + exited = true; + } + }; + + private static void initializeGUI() { + frame = new Frame("MouseEnterExitTest"); + frame.setLayout(new FlowLayout()); + List list = new List(4); + for (int i = 0; i < 10; i++) { + list.add("item " + i); + } + list.addMouseListener(mouseListener); + frame.add(list); + + TextArea textArea = new TextArea("TextArea", 10, 20); + textArea.addMouseListener(mouseListener); + frame.add(textArea); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + EventQueue.invokeAndWait(MouseEnterExitTest::initializeGUI); + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + compAt = frame.getLocationOnScreen(); + compSize = frame.getSize(); + }); + compAt.y += compSize.getHeight() / 2; + int xr = compAt.x + compSize.width + 1; + for (int i = compAt.x - 5; (i < xr) && passed; i++) { + robot.mouseMove(i, compAt.y); + } + + if (!passed || entered || !exited) { + throw new RuntimeException( + "MouseEnterExitTest FAILED. MouseEntered/MouseExited " + + "not properly triggered. Please see the log"); + } + System.out.println("Test PASSED"); + } finally { + EventQueue.invokeAndWait(MouseEnterExitTest::disposeFrame); + } + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + } + } +} From 7633a76607e264ce578f3c0e1d393c1016bc6b95 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 12 Oct 2023 09:50:18 +0000 Subject: [PATCH 003/111] 8317998: Temporarily disable malformed control flow assert to reduce noise in testing Reviewed-by: epeter --- src/hotspot/share/opto/compile.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 42729fcd214..8ea8095413b 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -4009,8 +4009,6 @@ bool Compile::final_graph_reshaping() { // Recheck with a better notion of 'required_outcnt' if (n->outcnt() != required_outcnt) { - DEBUG_ONLY( n->dump_bfs(1, 0, "-"); ); - assert(false, "malformed control flow"); record_method_not_compilable("malformed control flow"); return true; // Not all targets reachable! } From 4c79e7d59caec01b4d2bdae2f7d25f1dd24ffbf6 Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Thu, 12 Oct 2023 10:28:52 +0000 Subject: [PATCH 004/111] 8170817: G1: Returning MinTLABSize from unsafe_max_tlab_alloc causes TLAB flapping Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1Allocator.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index cf44b68fc86..ffd2b65f555 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -191,11 +191,14 @@ size_t G1Allocator::unsafe_max_tlab_alloc() { uint node_index = current_node_index(); HeapRegion* hr = mutator_alloc_region(node_index)->get(); size_t max_tlab = _g1h->max_tlab_size() * wordSize; - if (hr == nullptr) { + + if (hr == nullptr || hr->free() < MinTLABSize) { + // The next TLAB allocation will most probably happen in a new region, + // therefore we can attempt to allocate the maximum allowed TLAB size. return max_tlab; - } else { - return clamp(hr->free(), MinTLABSize, max_tlab); } + + return MIN2(hr->free(), max_tlab); } size_t G1Allocator::used_in_alloc_regions() { From 32ccf018eb32726e60126dcfd69d1be9ac80ec42 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 12 Oct 2023 13:48:59 +0000 Subject: [PATCH 005/111] 8317772: NMT: Make peak values available in release builds Reviewed-by: jsjolen, zgu --- src/hotspot/share/services/mallocTracker.cpp | 2 -- src/hotspot/share/services/mallocTracker.hpp | 15 +++++---------- src/hotspot/share/services/memReporter.cpp | 2 +- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/services/mallocTracker.cpp b/src/hotspot/share/services/mallocTracker.cpp index bddfcfffc08..0793ca6f4e9 100644 --- a/src/hotspot/share/services/mallocTracker.cpp +++ b/src/hotspot/share/services/mallocTracker.cpp @@ -45,7 +45,6 @@ size_t MallocMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(MallocMemorySnapshot, size_t)]; -#ifdef ASSERT void MemoryCounter::update_peak(size_t size, size_t cnt) { size_t peak_sz = peak_size(); while (peak_sz < size) { @@ -59,7 +58,6 @@ void MemoryCounter::update_peak(size_t size, size_t cnt) { } } } -#endif // ASSERT // Total malloc'd memory used by arenas size_t MallocMemorySnapshot::total_arena() const { diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index 4088abd7005..10eb7e063f7 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -46,25 +46,20 @@ class MemoryCounter { volatile size_t _count; volatile size_t _size; -#ifdef ASSERT // Peak size and count. Note: Peak count is the count at the point // peak size was reached, not the absolute highest peak count. volatile size_t _peak_count; volatile size_t _peak_size; void update_peak(size_t size, size_t cnt); -#endif // ASSERT public: - MemoryCounter() : _count(0), _size(0) { - DEBUG_ONLY(_peak_count = 0;) - DEBUG_ONLY(_peak_size = 0;) - } + MemoryCounter() : _count(0), _size(0), _peak_count(0), _peak_size(0) {} inline void allocate(size_t sz) { size_t cnt = Atomic::add(&_count, size_t(1), memory_order_relaxed); if (sz > 0) { size_t sum = Atomic::add(&_size, sz, memory_order_relaxed); - DEBUG_ONLY(update_peak(sum, cnt);) + update_peak(sum, cnt); } } @@ -81,7 +76,7 @@ class MemoryCounter { if (sz != 0) { assert(sz >= 0 || size() >= size_t(-sz), "Must be"); size_t sum = Atomic::add(&_size, size_t(sz), memory_order_relaxed); - DEBUG_ONLY(update_peak(sum, _count);) + update_peak(sum, _count); } } @@ -89,11 +84,11 @@ class MemoryCounter { inline size_t size() const { return Atomic::load(&_size); } inline size_t peak_count() const { - return DEBUG_ONLY(Atomic::load(&_peak_count)) NOT_DEBUG(0); + return Atomic::load(&_peak_count); } inline size_t peak_size() const { - return DEBUG_ONLY(Atomic::load(&_peak_size)) NOT_DEBUG(0); + return Atomic::load(&_peak_size); } }; diff --git a/src/hotspot/share/services/memReporter.cpp b/src/hotspot/share/services/memReporter.cpp index 3e2927a8bad..a277fec5c80 100644 --- a/src/hotspot/share/services/memReporter.cpp +++ b/src/hotspot/share/services/memReporter.cpp @@ -246,7 +246,7 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, // report malloc'd memory if (amount_in_current_scale(malloc_memory->malloc_size()) > 0 - DEBUG_ONLY(|| amount_in_current_scale(malloc_memory->malloc_peak_size()) > 0)) { + || amount_in_current_scale(malloc_memory->malloc_peak_size()) > 0) { print_malloc_line(malloc_memory->malloc_counter()); } From 935543146b23f22a73e14c6789cf73db7c3d466b Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 12 Oct 2023 13:54:09 +0000 Subject: [PATCH 006/111] 8316426: Optimization for HexFormat.formatHex Reviewed-by: liach, rriggs --- .../share/classes/java/util/HexFormat.java | 53 +++++++++---------- .../classes/jdk/internal/util/HexDigits.java | 24 +++++++++ .../bench/java/util/HexFormatBench.java | 19 +++++++ 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/src/java.base/share/classes/java/util/HexFormat.java b/src/java.base/share/classes/java/util/HexFormat.java index d54d491f3ab..b8c3a06e7ee 100644 --- a/src/java.base/share/classes/java/util/HexFormat.java +++ b/src/java.base/share/classes/java/util/HexFormat.java @@ -27,6 +27,7 @@ import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.util.HexDigits; import java.io.IOException; import java.io.UncheckedIOException; @@ -150,15 +151,7 @@ public final class HexFormat { -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; /** * Format each byte of an array as a pair of hexadecimal digits. @@ -403,21 +396,20 @@ public A formatHex(A out, byte[] bytes, int fromIndex, in int length = toIndex - fromIndex; if (length > 0) { try { - out.append(prefix); - toHexDigits(out, bytes[fromIndex]); - if (suffix.isEmpty() && delimiter.isEmpty() && prefix.isEmpty()) { - for (int i = 1; i < length; i++) { - toHexDigits(out, bytes[fromIndex + i]); - } + String s = formatOptDelimiter(bytes, fromIndex, toIndex); + if (s != null) { + out.append(s); } else { + out.append(prefix); + toHexDigits(out, bytes[fromIndex]); for (int i = 1; i < length; i++) { out.append(suffix); out.append(delimiter); out.append(prefix); toHexDigits(out, bytes[fromIndex + i]); } + out.append(suffix); } - out.append(suffix); } catch (IOException ioe) { throw new UncheckedIOException(ioe.getMessage(), ioe); } @@ -438,29 +430,36 @@ public A formatHex(A out, byte[] bytes, int fromIndex, in * or non-empty prefix or suffix */ private String formatOptDelimiter(byte[] bytes, int fromIndex, int toIndex) { + char sep; byte[] rep; if (!prefix.isEmpty() || !suffix.isEmpty()) { return null; } + + boolean ucase = digitCase == Case.UPPERCASE; int length = toIndex - fromIndex; if (delimiter.isEmpty()) { // Allocate the byte array and fill in the hex pairs for each byte rep = new byte[checkMaxArraySize(length * 2L)]; for (int i = 0; i < length; i++) { - rep[i * 2] = (byte)toHighHexDigit(bytes[fromIndex + i]); - rep[i * 2 + 1] = (byte)toLowHexDigit(bytes[fromIndex + i]); + short pair = HexDigits.digitPair(bytes[fromIndex + i], ucase); + int pos = i * 2; + rep[pos] = (byte)pair; + rep[pos + 1] = (byte)(pair >>> 8); } - } else if (delimiter.length() == 1 && delimiter.charAt(0) < 256) { + } else if (delimiter.length() == 1 && (sep = delimiter.charAt(0)) < 256) { // Allocate the byte array and fill in the characters for the first byte // Then insert the delimiter and hexadecimal characters for each of the remaining bytes - char sep = delimiter.charAt(0); rep = new byte[checkMaxArraySize(length * 3L - 1L)]; - rep[0] = (byte) toHighHexDigit(bytes[fromIndex]); - rep[1] = (byte) toLowHexDigit(bytes[fromIndex]); + short pair = HexDigits.digitPair(bytes[fromIndex], ucase); + rep[0] = (byte)pair; + rep[1] = (byte)(pair >>> 8); for (int i = 1; i < length; i++) { - rep[i * 3 - 1] = (byte) sep; - rep[i * 3 ] = (byte) toHighHexDigit(bytes[fromIndex + i]); - rep[i * 3 + 1] = (byte) toLowHexDigit(bytes[fromIndex + i]); + int pos = i * 3; + pair = HexDigits.digitPair(bytes[fromIndex + i], ucase); + rep[pos - 1] = (byte) sep; + rep[pos] = (byte)pair; + rep[pos + 1] = (byte)(pair >>> 8); } } else { // Delimiter formatting not to a single byte @@ -887,7 +886,7 @@ private static int checkDigitCount(int fromIndex, int toIndex, int limit) { * otherwise {@code false} */ public static boolean isHexDigit(int ch) { - return ((ch >>> 8) == 0 && DIGITS[ch] >= 0); + return ((ch >>> 7) == 0 && DIGITS[ch] >= 0); } /** @@ -905,7 +904,7 @@ public static boolean isHexDigit(int ch) { */ public static int fromHexDigit(int ch) { int value; - if ((ch >>> 8) == 0 && (value = DIGITS[ch]) >= 0) { + if ((ch >>> 7) == 0 && (value = DIGITS[ch]) >= 0) { return value; } throw new NumberFormatException("not a hexadecimal digit: \"" + (char) ch + "\" = " + ch); diff --git a/src/java.base/share/classes/jdk/internal/util/HexDigits.java b/src/java.base/share/classes/jdk/internal/util/HexDigits.java index 5ffb454ae00..1adda90a65a 100644 --- a/src/java.base/share/classes/jdk/internal/util/HexDigits.java +++ b/src/java.base/share/classes/jdk/internal/util/HexDigits.java @@ -91,6 +91,30 @@ public final class HexDigits implements Digits { private HexDigits() { } + /** + * For values from 0 to 255 return a short encoding a pair of hex ASCII-encoded digit characters in little-endian + * @param i value to convert + * @param ucase true uppper case, false lower case + * @return a short encoding a pair of hex ASCII-encoded digit characters + */ + public static short digitPair(int i, boolean ucase) { + /* + * 0b0100_0000_0100_0000 is a selector that selects letters (1 << 6), + * uppercase or not, and shifting it right by 1 bit incidentally + * becomes a bit offset between cases (1 << 5). + * + * ([0-9] & 0b100_0000) >> 1 => 0 + * ([a-f] & 0b100_0000) >> 1 => 32 + * + * [0-9] - 0 => [0-9] + * [a-f] - 32 => [A-F] + */ + short v = DIGITS[i & 0xff]; + return ucase + ? (short) (v - ((v & 0b0100_0000_0100_0000) >> 1)) + : v; + } + /** * Return a little-endian packed integer for the 4 ASCII bytes for an input unsigned 2-byte integer. * {@code b0} is the most significant byte and {@code b1} is the least significant byte. diff --git a/test/micro/org/openjdk/bench/java/util/HexFormatBench.java b/test/micro/org/openjdk/bench/java/util/HexFormatBench.java index c554f70c351..aa81a7c25ba 100644 --- a/test/micro/org/openjdk/bench/java/util/HexFormatBench.java +++ b/test/micro/org/openjdk/bench/java/util/HexFormatBench.java @@ -93,6 +93,25 @@ public StringBuilder appenderUpperCached() { return UPPER_FORMATTER.formatHex(builder, bytes); } + @Benchmark + public String formatLower() { + return HexFormat.of().formatHex(bytes); + } + + @Benchmark + public String formatUpper() { + return HexFormat.of().withUpperCase().formatHex(bytes); + } + + @Benchmark + public String formatLowerCached() { + return LOWER_FORMATTER.formatHex(bytes); + } + + @Benchmark + public String formatUpperCached() { + return UPPER_FORMATTER.formatHex(bytes); + } @Benchmark public void toHexLower(Blackhole bh) { From c1f698d38bb251941598af5a82a1a230282b718d Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 12 Oct 2023 14:14:43 +0000 Subject: [PATCH 007/111] 8317956: Make jdk.internal.util.Architecture current architecture final Reviewed-by: pminborg, redestad, bpb --- src/java.base/share/classes/jdk/internal/util/Architecture.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/jdk/internal/util/Architecture.java b/src/java.base/share/classes/jdk/internal/util/Architecture.java index 5c861902743..4f193e75597 100644 --- a/src/java.base/share/classes/jdk/internal/util/Architecture.java +++ b/src/java.base/share/classes/jdk/internal/util/Architecture.java @@ -114,7 +114,7 @@ private static Architecture initArch(String archName) { } // Initialize the architecture by mapping aliases and names to the enum values. - private static Architecture CURRENT_ARCH = initArch(PlatformProps.CURRENT_ARCH_STRING); + private static final Architecture CURRENT_ARCH = initArch(PlatformProps.CURRENT_ARCH_STRING); /** * {@return {@code true} if the current architecture is X64, Aka amd64} From 16fd43c5eb0fb18e93f00b5817d368df5afad969 Mon Sep 17 00:00:00 2001 From: Mikhailo Seledtsov Date: Thu, 12 Oct 2023 16:29:14 +0000 Subject: [PATCH 008/111] 8316693: Simplify at-requires checkDockerSupport() Reviewed-by: iklam, lmesnik --- test/jtreg-ext/requires/VMProps.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 31df96fd80e..01077c15de0 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -602,9 +602,10 @@ private void printLogfileContent(Map logFileNames) { private boolean checkDockerSupport() throws IOException, InterruptedException { log("checkDockerSupport(): entering"); - ProcessBuilder pb = new ProcessBuilder(Container.ENGINE_COMMAND, "ps"); - Map logFileNames = redirectOutputToLogFile("checkDockerSupport(): ps", - pb, "container-ps"); + ProcessBuilder pb = new ProcessBuilder("which", Container.ENGINE_COMMAND); + Map logFileNames = + redirectOutputToLogFile("checkDockerSupport(): which ", + pb, "which-container"); Process p = pb.start(); p.waitFor(10, TimeUnit.SECONDS); int exitValue = p.exitValue(); From a8473b70797ef8fa0704774bfadbd84cb33a1d53 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Thu, 12 Oct 2023 16:51:53 +0000 Subject: [PATCH 009/111] 8317336: Assertion error thrown during 'this' escape analysis Reviewed-by: vromero --- .../sun/tools/javac/comp/ThisEscapeAnalyzer.java | 11 +++++++++-- .../tools/javac/warnings/ThisEscape.java | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java index 7f7f09b3391..2dd054619e0 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java @@ -678,7 +678,11 @@ public void visitForLoop(JCForLoop tree) { @Override public void visitForeachLoop(JCEnhancedForLoop tree) { - visitLooped(tree, super::visitForeachLoop); + visitLooped(tree, foreach -> { + scan(foreach.expr); + refs.discardExprs(depth); // we don't handle iterator() yet + scan(foreach.body); + }); } @Override @@ -729,7 +733,10 @@ public void visitReturn(JCReturn tree) { @Override public void visitLambda(JCLambda lambda) { - visitDeferred(() -> visitScoped(false, () -> super.visitLambda(lambda))); + visitDeferred(() -> visitScoped(false, () -> { + scan(lambda.body); + refs.discardExprs(depth); // needed in case body is a JCExpression + })); } @Override diff --git a/test/langtools/tools/javac/warnings/ThisEscape.java b/test/langtools/tools/javac/warnings/ThisEscape.java index 65bca36923b..d6ae9f8e8f4 100644 --- a/test/langtools/tools/javac/warnings/ThisEscape.java +++ b/test/langtools/tools/javac/warnings/ThisEscape.java @@ -601,4 +601,20 @@ public static final class Sub1 extends ThisEscapeSealed { public static final class Sub2 extends ThisEscapeSealed { } } + + // Verify no assertion error occurs (JDK-8317336) + public static class ThisEscapeAssertionError { + public ThisEscapeAssertionError() { + System.out.println((Supplier)() -> this); + } + } + + // Verify no assertion error occurs (JDK-8317336) + public static class ThisEscapeAssertionError2 { + public ThisEscapeAssertionError2() { + ThisEscapeAssertionError2[] array = new ThisEscapeAssertionError2[] { this }; + for (Object obj : array) + ; + } + } } From 9728e21db1b35e487c562690de659aac386aa99d Mon Sep 17 00:00:00 2001 From: Rajan Halade Date: Thu, 12 Oct 2023 17:02:32 +0000 Subject: [PATCH 010/111] 8317967: Enhance test/jdk/javax/net/ssl/TLSCommon/SSLEngineTestCase.java to handle default cases Reviewed-by: mullan --- .../javax/net/ssl/TLSCommon/SSLEngineTestCase.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/net/ssl/TLSCommon/SSLEngineTestCase.java b/test/jdk/javax/net/ssl/TLSCommon/SSLEngineTestCase.java index 57548ce750d..dce28edadf2 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/SSLEngineTestCase.java +++ b/test/jdk/javax/net/ssl/TLSCommon/SSLEngineTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -134,7 +134,7 @@ public enum HandshakeMode { * e.g. "TLSv1", "TLSv1.1", "TLSv1.2", "DTLSv1.0", "DTLSv1.2". */ public static final String TESTED_SECURITY_PROTOCOL - = System.getProperty("test.security.protocol", "TLS"); + = System.getProperty("test.security.protocol"); /** * Test mode: "norm", "norm_sni" or "krb". * Modes "norm" and "norm_sni" are used to run @@ -738,13 +738,18 @@ public void runTests() { case "TLSv1.1": runTests(Ciphers.SUPPORTED_NON_KRB_NON_SHA_CIPHERS); break; - case "DTLSv1.1": + case "DTLS": + case "DTLSv1.2": + case "TLS": case "TLSv1.2": runTests(Ciphers.SUPPORTED_NON_KRB_CIPHERS); break; case "TLSv1.3": runTests(Ciphers.TLS13_CIPHERS); break; + default: + throw new Error("Test error: Unsupported test " + + "security protocol: " + TESTED_SECURITY_PROTOCOL); } break; case "krb": From 32ac72c3d35138f5253e4defc948304ac3ea1b53 Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Thu, 12 Oct 2023 19:50:08 +0000 Subject: [PATCH 011/111] 8312522: Implementation of Foreign Function & Memory API Co-authored-by: Maurizio Cimadamore Co-authored-by: Jorn Vernee Co-authored-by: Per Minborg Reviewed-by: dholmes, psandoz, mcimadamore, alanb --- .github/workflows/main.yml | 6 +- make/conf/jib-profiles.js | 11 +- .../share/classes/java/lang/Class.java | 2 + .../share/classes/java/lang/Module.java | 15 +- .../share/classes/java/lang/ModuleLayer.java | 9 +- .../share/classes/java/lang/System.java | 4 +- .../java/lang/foreign/AddressLayout.java | 12 +- .../classes/java/lang/foreign/Arena.java | 10 +- .../java/lang/foreign/FunctionDescriptor.java | 4 +- .../java/lang/foreign/GroupLayout.java | 4 +- .../classes/java/lang/foreign/Linker.java | 174 ++++--- .../java/lang/foreign/MemoryLayout.java | 268 ++++++---- .../java/lang/foreign/MemorySegment.java | 372 ++++++++------ .../java/lang/foreign/PaddingLayout.java | 4 +- .../java/lang/foreign/SegmentAllocator.java | 471 +++++++++++------- .../java/lang/foreign/SequenceLayout.java | 4 +- .../java/lang/foreign/StructLayout.java | 4 +- .../java/lang/foreign/SymbolLookup.java | 10 +- .../java/lang/foreign/UnionLayout.java | 4 +- .../java/lang/foreign/ValueLayout.java | 128 ++--- .../java/lang/foreign/package-info.java | 8 +- .../lang/foreign/snippet-files/Snippets.java | 44 +- .../java/lang/invoke/MethodHandles.java | 103 +--- .../lang/invoke/VarHandleSegmentViewBase.java | 6 +- .../X-VarHandleSegmentView.java.template | 109 ++-- .../java/nio/channels/FileChannel.java | 3 +- .../classes/java/util/jar/Attributes.java | 5 +- .../jdk/internal/access/JavaLangAccess.java | 2 +- .../foreign/AbstractMemorySegmentImpl.java | 11 +- .../jdk/internal/foreign/ArenaImpl.java | 63 +++ .../jdk/internal/foreign/LayoutPath.java | 50 +- .../internal/foreign/MemorySessionImpl.java | 17 +- .../foreign/NativeMemorySegmentImpl.java | 26 +- .../internal/foreign/SlicingAllocator.java | 2 - .../jdk/internal/foreign/StringSupport.java | 154 ++++++ .../classes/jdk/internal/foreign/Utils.java | 28 +- .../internal/foreign/abi/AbstractLinker.java | 24 +- .../foreign/abi/BindingInterpreter.java | 4 +- .../internal/foreign/abi/CallingSequence.java | 2 +- .../internal/foreign/abi/LinkerOptions.java | 18 +- .../jdk/internal/foreign/abi/SharedUtils.java | 67 ++- .../abi/aarch64/linux/LinuxAArch64Linker.java | 12 + .../abi/aarch64/macos/MacOsAArch64Linker.java | 12 + .../aarch64/windows/WindowsAArch64Linker.java | 12 + .../foreign/abi/fallback/FFIType.java | 35 +- .../foreign/abi/fallback/FallbackLinker.java | 52 ++ .../foreign/abi/fallback/LibFallback.java | 15 + .../abi/ppc64/linux/LinuxPPC64Linker.java | 12 + .../abi/ppc64/linux/LinuxPPC64leLinker.java | 12 + .../abi/riscv64/linux/LinuxRISCV64Linker.java | 12 + .../abi/s390/linux/LinuxS390Linker.java | 12 + .../foreign/abi/x64/sysv/SysVx64Linker.java | 12 + .../abi/x64/windows/Windowsx64Linker.java | 12 + .../foreign/layout/AbstractGroupLayout.java | 2 - .../foreign/layout/AbstractLayout.java | 3 +- .../internal/foreign/layout/ValueLayouts.java | 25 +- .../jdk/internal/javac/PreviewFeature.java | 4 +- .../share/classes/jdk/internal/misc/VM.java | 1 + .../classes/jdk/internal/module/Modules.java | 9 +- .../jdk/internal/reflect/Reflection.java | 8 +- src/java.base/share/classes/module-info.java | 2 +- .../classes/sun/launcher/LauncherHelper.java | 8 + .../launcher/resources/launcher.properties | 2 + .../native/libfallbackLinker/fallbackLinker.c | 21 + .../share/classes/module-info.java | 3 - .../TestRangeCheckHoistingScaledIV.java | 5 +- .../vectorapi/TestIntrinsicBailOut.java | 1 - .../vectorapi/TestVectorErgonomics.java | 14 +- .../compiler/vectorapi/VectorMemoryAlias.java | 3 +- .../vectorapi/VectorRebracket128Test.java | 4 +- .../vectorapi/reshape/TestVectorCastAVX1.java | 3 +- .../vectorapi/reshape/TestVectorCastAVX2.java | 3 +- .../reshape/TestVectorCastAVX512.java | 3 +- .../reshape/TestVectorCastAVX512BW.java | 3 +- .../reshape/TestVectorCastAVX512DQ.java | 3 +- .../vectorapi/reshape/TestVectorCastNeon.java | 3 +- .../vectorapi/reshape/TestVectorCastSVE.java | 3 +- .../reshape/TestVectorReinterpret.java | 3 +- .../reshape/utils/VectorReshapeHelper.java | 4 +- .../compiler/TestLinkToNativeRBP.java | 1 - .../ClassFile/ClassFileVersionTest.java | 4 +- .../jdk/java/foreign/CompositeLookupTest.java | 1 - test/jdk/java/foreign/LibraryLookupTest.java | 2 - .../MemoryLayoutPrincipalTotalityTest.java | 1 - .../MemoryLayoutTypeRetentionTest.java | 1 - test/jdk/java/foreign/NativeTestHelper.java | 47 +- .../java/foreign/SafeFunctionAccessTest.java | 2 - test/jdk/java/foreign/StdLibTest.java | 61 ++- test/jdk/java/foreign/TestAccessModes.java | 179 +++++++ .../jdk/java/foreign/TestAdaptVarHandles.java | 52 +- .../java/foreign/TestAddressDereference.java | 31 +- test/jdk/java/foreign/TestArrayCopy.java | 16 +- test/jdk/java/foreign/TestArrays.java | 32 +- test/jdk/java/foreign/TestByteBuffer.java | 9 +- .../foreign/TestClassLoaderFindNative.java | 2 - .../jdk/java/foreign/TestDereferencePath.java | 17 +- test/jdk/java/foreign/TestDowncallScope.java | 2 - test/jdk/java/foreign/TestDowncallStack.java | 2 - test/jdk/java/foreign/TestFallbackLookup.java | 4 +- test/jdk/java/foreign/TestFree.java | 5 +- .../java/foreign/TestFunctionDescriptor.java | 2 - test/jdk/java/foreign/TestHFA.java | 2 - test/jdk/java/foreign/TestHandshake.java | 1 - test/jdk/java/foreign/TestHeapAlignment.java | 10 +- test/jdk/java/foreign/TestIllegalLink.java | 35 +- test/jdk/java/foreign/TestIntrinsics.java | 2 - .../java/foreign/TestLargeSegmentCopy.java | 1 - test/jdk/java/foreign/TestLayoutPaths.java | 10 +- test/jdk/java/foreign/TestLayouts.java | 58 ++- test/jdk/java/foreign/TestLinker.java | 46 +- test/jdk/java/foreign/TestMatrix.java | 44 +- test/jdk/java/foreign/TestMemoryAccess.java | 106 ++-- .../foreign/TestMemoryAccessInstance.java | 1 - .../jdk/java/foreign/TestMemoryAlignment.java | 21 +- .../java/foreign/TestMemoryDereference.java | 3 +- test/jdk/java/foreign/TestMemorySession.java | 1 - test/jdk/java/foreign/TestMismatch.java | 1 - test/jdk/java/foreign/TestNULLAddress.java | 2 - test/jdk/java/foreign/TestNative.java | 30 +- test/jdk/java/foreign/TestNulls.java | 4 +- test/jdk/java/foreign/TestOfBufferIssue.java | 3 +- test/jdk/java/foreign/TestReshape.java | 3 +- test/jdk/java/foreign/TestRestricted.java | 1 - .../java/foreign/TestScopedOperations.java | 32 +- .../java/foreign/TestSegmentAllocators.java | 89 ++-- test/jdk/java/foreign/TestSegmentCopy.java | 3 +- test/jdk/java/foreign/TestSegmentOffset.java | 22 +- test/jdk/java/foreign/TestSegmentOverlap.java | 1 - test/jdk/java/foreign/TestSegments.java | 9 +- test/jdk/java/foreign/TestSharedAccess.java | 5 +- test/jdk/java/foreign/TestSlices.java | 9 +- test/jdk/java/foreign/TestSpliterator.java | 11 +- test/jdk/java/foreign/TestStringEncoding.java | 60 ++- test/jdk/java/foreign/TestTypeAccess.java | 13 +- .../java/foreign/TestUnsupportedLinker.java | 41 -- test/jdk/java/foreign/TestUpcallAsync.java | 2 - .../jdk/java/foreign/TestUpcallException.java | 2 - .../jdk/java/foreign/TestUpcallHighArity.java | 11 - test/jdk/java/foreign/TestUpcallScope.java | 2 - test/jdk/java/foreign/TestUpcallStack.java | 2 - .../java/foreign/TestUpcallStructScope.java | 11 - test/jdk/java/foreign/TestValueLayouts.java | 3 +- test/jdk/java/foreign/TestVarArgs.java | 14 +- .../foreign/TestVarHandleCombinators.java | 15 +- test/jdk/java/foreign/UpcallTestHelper.java | 1 - .../arraystructs/TestArrayStructs.java | 4 - .../callarranger/TestLayoutEquality.java | 1 - .../TestLinuxAArch64CallArranger.java | 1 - .../TestMacOsAArch64CallArranger.java | 1 - .../callarranger/TestRISCV64CallArranger.java | 1 - .../callarranger/TestSysVCallArranger.java | 1 - .../TestWindowsAArch64CallArranger.java | 1 - .../callarranger/TestWindowsCallArranger.java | 1 - .../TestCaptureCallState.java | 64 +-- .../channels/TestAsyncSocketChannels.java | 1 - .../foreign/channels/TestSocketChannels.java | 1 - .../foreign/dontrelease/TestDontRelease.java | 2 - .../TestEnableNativeAccess.java | 98 +--- .../TestEnableNativeAccessBase.java | 124 +++++ .../TestEnableNativeAccessDynamic.java | 87 +--- .../TestEnableNativeAccessJarManifest.java | 141 ++++++ .../PanamaMainUnnamedModule.java | 2 +- .../{ => unnamed}/libLinkerInvokerUnnamed.cpp | 2 +- .../org/openjdk/foreigntest/PanamaMain.java | 34 -- .../foreigntest/libLinkerInvokerModule.cpp | 9 +- test/jdk/java/foreign/handles/Driver.java | 4 +- .../java/foreign/largestub/TestLargeStub.java | 2 - .../loaderLookup/TestLoaderLookup.java | 4 +- .../loaderLookup/TestLoaderLookupJNI.java | 4 +- test/jdk/java/foreign/nested/TestNested.java | 2 - .../java/foreign/normalize/TestNormalize.java | 2 - .../passheapsegment/TestPassHeapSegment.java | 4 +- .../foreign/stackwalk/TestAsyncStackWalk.java | 8 - .../stackwalk/TestReentrantUpcalls.java | 2 - .../java/foreign/stackwalk/TestStackWalk.java | 8 - .../{TestTrivial.java => TestCritical.java} | 33 +- ...ialUpcall.java => TestCriticalUpcall.java} | 10 +- .../trivial/{libTrivial.c => libCritical.c} | 4 - .../foreign/upcalldeopt/TestUpcallDeopt.java | 2 - .../foreign/virtual/TestVirtualCalls.java | 4 +- .../jni/AttachCurrentThread/AttachTest.java | 10 +- .../VarHandles/IndirectVarHandleTest.java | 1 - .../invoke/VarHandles/VarHandleTestExact.java | 3 +- .../channels/FileChannel/LargeMapTest.java | 3 +- .../FileChannel/MapToMemorySegmentTest.java | 3 +- .../jdk/java/util/stream/test/TEST.properties | 3 - .../vector/Byte128VectorLoadStoreTests.java | 3 +- .../vector/Byte256VectorLoadStoreTests.java | 3 +- .../vector/Byte512VectorLoadStoreTests.java | 3 +- .../vector/Byte64VectorLoadStoreTests.java | 3 +- .../vector/ByteMaxVectorLoadStoreTests.java | 3 +- .../vector/Double128VectorLoadStoreTests.java | 3 +- .../vector/Double256VectorLoadStoreTests.java | 3 +- .../vector/Double512VectorLoadStoreTests.java | 3 +- .../vector/Double64VectorLoadStoreTests.java | 3 +- .../vector/DoubleMaxVectorLoadStoreTests.java | 3 +- .../vector/Float128VectorLoadStoreTests.java | 3 +- .../vector/Float256VectorLoadStoreTests.java | 3 +- .../vector/Float512VectorLoadStoreTests.java | 3 +- .../vector/Float64VectorLoadStoreTests.java | 3 +- .../vector/FloatMaxVectorLoadStoreTests.java | 3 +- .../vector/Int128VectorLoadStoreTests.java | 3 +- .../vector/Int256VectorLoadStoreTests.java | 3 +- .../vector/Int512VectorLoadStoreTests.java | 3 +- .../vector/Int64VectorLoadStoreTests.java | 3 +- .../vector/IntMaxVectorLoadStoreTests.java | 3 +- .../vector/Long128VectorLoadStoreTests.java | 3 +- .../vector/Long256VectorLoadStoreTests.java | 3 +- .../vector/Long512VectorLoadStoreTests.java | 3 +- .../vector/Long64VectorLoadStoreTests.java | 3 +- .../vector/LongMaxVectorLoadStoreTests.java | 3 +- .../vector/Short128VectorLoadStoreTests.java | 3 +- .../vector/Short256VectorLoadStoreTests.java | 3 +- .../vector/Short512VectorLoadStoreTests.java | 3 +- .../vector/Short64VectorLoadStoreTests.java | 3 +- .../vector/ShortMaxVectorLoadStoreTests.java | 3 +- .../incubator/vector/VectorReshapeTests.java | 3 +- .../templates/X-LoadStoreTest.java.template | 3 +- .../tools/javac/RestrictedMethods.java | 4 +- .../tools/javac/RestrictedMethods.out | 2 - .../java/lang/foreign/AllocFromSliceTest.java | 80 +++ .../java/lang/foreign/AllocFromTest.java | 176 +++++++ .../bench/java/lang/foreign/BulkOps.java | 4 +- .../bench/java/lang/foreign/CLayouts.java | 4 +- .../lang/foreign/CallOverheadConstant.java | 12 +- .../java/lang/foreign/CallOverheadHelper.java | 18 +- .../lang/foreign/CallOverheadVirtual.java | 12 +- .../bench/java/lang/foreign/JavaLayouts.java | 21 +- .../bench/java/lang/foreign/LinkUpcall.java | 4 +- .../java/lang/foreign/LoopOverConstant.java | 4 +- .../bench/java/lang/foreign/LoopOverNew.java | 4 +- .../java/lang/foreign/LoopOverNewHeap.java | 4 +- .../lang/foreign/LoopOverNonConstant.java | 4 +- .../lang/foreign/LoopOverNonConstantFP.java | 4 +- .../lang/foreign/LoopOverNonConstantHeap.java | 4 +- .../foreign/LoopOverNonConstantMapped.java | 4 +- .../foreign/LoopOverNonConstantShared.java | 4 +- .../java/lang/foreign/LoopOverOfAddress.java | 4 +- .../lang/foreign/LoopOverPollutedBuffer.java | 4 +- .../foreign/LoopOverPollutedSegments.java | 4 +- .../java/lang/foreign/LoopOverSlice.java | 4 +- .../lang/foreign/MemorySegmentCopyUnsafe.java | 73 +++ .../lang/foreign/MemorySegmentGetUnsafe.java | 96 ++++ .../lang/foreign/MemorySegmentVsBits.java | 4 +- .../java/lang/foreign/MemorySessionClose.java | 4 +- .../bench/java/lang/foreign/ParallelSum.java | 4 +- .../java/lang/foreign/PointerInvoke.java | 4 +- .../bench/java/lang/foreign/QSort.java | 4 +- .../bench/java/lang/foreign/StrLenTest.java | 14 +- .../lang/foreign/TestAdaptVarHandles.java | 4 +- .../java/lang/foreign/TestLoadBytes.java | 7 +- .../java/lang/foreign/UnrolledAccess.java | 8 +- .../bench/java/lang/foreign/Upcalls.java | 4 +- .../java/lang/foreign/VarHandleExact.java | 6 +- .../lang/foreign/pointers/NativeType.java | 4 +- .../java/lang/foreign/pointers/Pointer.java | 4 +- .../lang/foreign/pointers/PointerBench.java | 6 +- .../foreign/points/support/PanamaPoint.java | 10 +- .../vector/MemorySegmentVectorAccess.java | 3 +- .../incubator/vector/TestLoadStoreBytes.java | 3 +- .../incubator/vector/TestLoadStoreShorts.java | 3 +- 261 files changed, 3142 insertions(+), 2127 deletions(-) create mode 100644 src/java.base/share/classes/jdk/internal/foreign/ArenaImpl.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/StringSupport.java create mode 100644 test/jdk/java/foreign/TestAccessModes.java delete mode 100644 test/jdk/java/foreign/TestUnsupportedLinker.java create mode 100644 test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java create mode 100644 test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java rename test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/{ => unnamed}/PanamaMainUnnamedModule.java (98%) rename test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/{ => unnamed}/libLinkerInvokerUnnamed.cpp (93%) delete mode 100644 test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java rename test/jdk/java/foreign/trivial/{TestTrivial.java => TestCritical.java} (67%) rename test/jdk/java/foreign/trivial/{TestTrivialUpcall.java => TestCriticalUpcall.java} (87%) rename test/jdk/java/foreign/trivial/{libTrivial.c => libCritical.c} (96%) create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a10fc88087b..2570efd8b74 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2022, 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 @@ -146,8 +146,8 @@ jobs: apt-architecture: 'i386' # Some multilib libraries do not have proper inter-dependencies, so we have to # install their dependencies manually. - apt-extra-packages: 'libfreetype-dev:i386 libtiff-dev:i386 libcupsimage2-dev:i386 libc6-i386 libgcc-s1:i386 libstdc++6:i386' - extra-conf-options: '--with-target-bits=32' + apt-extra-packages: 'libfreetype-dev:i386 libtiff-dev:i386 libcupsimage2-dev:i386 libc6-i386 libgcc-s1:i386 libstdc++6:i386 libffi-dev:i386' + extra-conf-options: '--with-target-bits=32 --enable-fallback-linker --enable-libffi-bundling' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} if: needs.select.outputs.linux-x86 == 'true' diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 8d9ec7e3bd6..5422bc05a7a 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -426,9 +426,14 @@ var getJibProfilesProfiles = function (input, common, data) { target_os: "linux", target_cpu: "x86", build_cpu: "x64", - dependencies: ["devkit", "gtest"], - configure_args: concat(common.configure_args_32bit, - "--with-jvm-variants=minimal,server", "--with-zlib=system"), + dependencies: ["devkit", "gtest", "libffi"], + configure_args: concat(common.configure_args_32bit, [ + "--with-jvm-variants=minimal,server", + "--with-zlib=system", + "--with-libffi=" + input.get("libffi", "home_path"), + "--enable-libffi-bundling", + "--enable-fallback-linker" + ]) }, "macosx-x64": { diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 991c8bcf646..c95aa764ee6 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -83,6 +83,7 @@ import jdk.internal.reflect.ReflectionFactory; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; +import jdk.internal.vm.annotation.Stable; import sun.invoke.util.Wrapper; import sun.reflect.generics.factory.CoreReflectionFactory; @@ -1060,6 +1061,7 @@ public Module getModule() { } // set by VM + @Stable private transient Module module; // Initialized in JVM not by private constructor diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index 33e92527488..694281bcca8 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -272,9 +272,8 @@ Module implAddEnableNativeAccess() { * restricted methods. * * @return {@code true} if this module can access restricted methods. - * @since 20 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) public boolean isNativeAccessEnabled() { Module target = moduleForNativeAccess(); return EnableNativeAccess.isNativeAccessEnabled(target); @@ -309,7 +308,7 @@ private Module moduleForNativeAccess() { } // This is invoked from Reflection.ensureNativeAccess - void ensureNativeAccess(Class owner, String methodName) { + void ensureNativeAccess(Class owner, String methodName, Class currentClass) { // The target module whose enableNativeAccess flag is ensured Module target = moduleForNativeAccess(); if (!EnableNativeAccess.isNativeAccessEnabled(target)) { @@ -320,13 +319,15 @@ void ensureNativeAccess(Class owner, String methodName) { // warn and set flag, so that only one warning is reported per module String cls = owner.getName(); String mtd = cls + "::" + methodName; - String mod = isNamed() ? "module " + getName() : "the unnamed module"; + String mod = isNamed() ? "module " + getName() : "an unnamed module"; String modflag = isNamed() ? getName() : "ALL-UNNAMED"; + String caller = currentClass != null ? currentClass.getName() : "code"; System.err.printf(""" WARNING: A restricted method in %s has been called - WARNING: %s has been called by %s - WARNING: Use --enable-native-access=%s to avoid a warning for this module - %n""", cls, mtd, mod, modflag); + WARNING: %s has been called by %s in %s + WARNING: Use --enable-native-access=%s to avoid a warning for callers in this module + WARNING: Restricted methods will be blocked in a future release unless native access is enabled + %n""", cls, mtd, caller, mod, modflag); } } } diff --git a/src/java.base/share/classes/java/lang/ModuleLayer.java b/src/java.base/share/classes/java/lang/ModuleLayer.java index fc74092f223..b038c1efa27 100644 --- a/src/java.base/share/classes/java/lang/ModuleLayer.java +++ b/src/java.base/share/classes/java/lang/ModuleLayer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -307,9 +307,7 @@ public Controller addOpens(Module source, String pn, Module target) { * *

This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain - * from depending on restricted methods, and use safe and supported functionalities, - * where possible. + * the JVM or, worse, silently result in memory corruption. * * @param target * The module to update @@ -322,9 +320,8 @@ public Controller addOpens(Module source, String pn, Module target) { * @throws IllegalCallerException * If the caller is in a module that does not have native access enabled * - * @since 20 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) @CallerSensitive @Restricted public Controller enableNativeAccess(Module target) { diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index e50858b26f1..da4fd4f358d 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -2454,8 +2454,8 @@ public Module addEnableNativeAccess(Module m) { public void addEnableNativeAccessToAllUnnamed() { Module.implAddEnableNativeAccessToAllUnnamed(); } - public void ensureNativeAccess(Module m, Class owner, String methodName) { - m.ensureNativeAccess(owner, methodName); + public void ensureNativeAccess(Module m, Class owner, String methodName, Class currentClass) { + m.ensureNativeAccess(owner, methodName, currentClass); } public ServicesCatalog getServicesCatalog(ModuleLayer layer) { return layer.getServicesCatalog(); diff --git a/src/java.base/share/classes/java/lang/foreign/AddressLayout.java b/src/java.base/share/classes/java/lang/foreign/AddressLayout.java index fd17f071fdf..6c93f4b64ed 100644 --- a/src/java.base/share/classes/java/lang/foreign/AddressLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/AddressLayout.java @@ -26,7 +26,6 @@ package java.lang.foreign; import jdk.internal.foreign.layout.ValueLayouts; -import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.Restricted; import jdk.internal.reflect.CallerSensitive; @@ -51,11 +50,13 @@ *

  • When creating an upcall stub, using {@link Linker#upcallStub(MethodHandle, FunctionDescriptor, Arena, Option...)}. * * + * @implSpec + * Implementations of this interface are immutable, thread-safe and value-based. + * * @see #ADDRESS * @see #ADDRESS_UNALIGNED - * @since 19 + * @since 22 */ -@PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) public sealed interface AddressLayout extends ValueLayout permits ValueLayouts.OfAddressImpl { /** @@ -95,13 +96,12 @@ public sealed interface AddressLayout extends ValueLayout permits ValueLayouts.O * {@snippet lang = java: * AddressLayout addressLayout = ... * AddressLayout unboundedLayout = addressLayout.withTargetLayout( - * MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)); + * MemoryLayout.sequenceLayout(Long.MAX_VALUE, ValueLayout.JAVA_BYTE)); *} *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @param layout the target layout. * @return an address layout with same characteristics as this layout, but with the provided target layout. diff --git a/src/java.base/share/classes/java/lang/foreign/Arena.java b/src/java.base/share/classes/java/lang/foreign/Arena.java index 1f3c1adc16d..457847d76c6 100644 --- a/src/java.base/share/classes/java/lang/foreign/Arena.java +++ b/src/java.base/share/classes/java/lang/foreign/Arena.java @@ -26,7 +26,6 @@ package java.lang.foreign; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.javac.PreviewFeature; import jdk.internal.ref.CleanerFactory; import java.lang.foreign.MemorySegment.Scope; @@ -184,7 +183,7 @@ * {@snippet lang = java: * try (Arena slicingArena = new SlicingArena(1000)) { * for (int i = 0; i < 10; i++) { - * MemorySegment s = slicingArena.allocateArray(JAVA_INT, 1, 2, 3, 4, 5); + * MemorySegment s = slicingArena.allocateFrom(JAVA_INT, 1, 2, 3, 4, 5); * ... * } * } // all memory allocated is released here @@ -195,9 +194,8 @@ * * @see MemorySegment * - * @since 20 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public interface Arena extends SegmentAllocator, AutoCloseable { /** @@ -269,9 +267,7 @@ static Arena ofShared() { * other than the arena's owner thread. */ @Override - default MemorySegment allocate(long byteSize, long byteAlignment) { - return ((MemorySessionImpl)scope()).allocate(byteSize, byteAlignment); - } + MemorySegment allocate(long byteSize, long byteAlignment); /** * {@return the arena scope} diff --git a/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java b/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java index 003eb7c3aa6..f715e4b91bd 100644 --- a/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java +++ b/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java @@ -32,7 +32,6 @@ import java.util.List; import jdk.internal.foreign.FunctionDescriptorImpl; -import jdk.internal.javac.PreviewFeature; /** * A function descriptor models the signature of a foreign function. A function descriptor is made up of zero or more @@ -44,9 +43,8 @@ * Implementing classes are immutable, thread-safe and value-based. * * @see MemoryLayout - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface FunctionDescriptor permits FunctionDescriptorImpl { /** diff --git a/src/java.base/share/classes/java/lang/foreign/GroupLayout.java b/src/java.base/share/classes/java/lang/foreign/GroupLayout.java index 177f1f1d5fa..e6654fcc8a5 100644 --- a/src/java.base/share/classes/java/lang/foreign/GroupLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/GroupLayout.java @@ -26,7 +26,6 @@ package java.lang.foreign; import java.util.List; -import jdk.internal.javac.PreviewFeature; /** * A compound layout that is an aggregation of multiple, heterogeneous member layouts. There are two ways in which member layouts @@ -38,9 +37,8 @@ * This class is immutable, thread-safe and value-based. * * @sealedGraph - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface GroupLayout extends MemoryLayout permits StructLayout, UnionLayout { /** 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 f9aecd4873b..9adca13b774 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -29,15 +29,12 @@ import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.CapturableState; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.Restricted; import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; import java.lang.invoke.MethodHandle; -import java.nio.ByteOrder; +import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -60,6 +57,12 @@ *

  • A linker allows foreign functions to call Java method handles, * via the generation of {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, Arena, Option...) upcall stubs}.
  • * + * A linker provides a way to look up the canonical layouts associated with the data types used by the ABI. + * For example, a linker implementing the C ABI might choose to provide a canonical layout for the C {@code size_t} + * type. On 64-bit platforms, this canonical layout might be equal to {@link ValueLayout#JAVA_LONG}. The canonical + * layouts supported by a linker are exposed via the {@link #canonicalLayouts()} method, which returns a map from + * type names to canonical layouts. + *

    * In addition, a linker provides a way to look up foreign functions in libraries that conform to the ABI. Each linker * chooses a set of libraries that are commonly used on the OS and processor combination associated with the ABI. * For example, a linker for Linux/x64 might choose two libraries: {@code libc} and {@code libm}. The functions in these @@ -93,10 +96,10 @@ * * {@snippet lang = java: * try (Arena arena = Arena.ofConfined()) { - * MemorySegment str = arena.allocateUtf8String("Hello"); + * MemorySegment str = arena.allocateFrom("Hello"); * long len = (long) strlen.invokeExact(str); // 5 * } - * } + *} *

    Describing C signatures

    * * When interacting with the native linker, clients must provide a platform-dependent description of the signature @@ -104,11 +107,8 @@ * defines the layouts associated with the parameter types and return type (if any) of the C function. *

    * Scalar C types such as {@code bool}, {@code int} are modelled as {@linkplain ValueLayout value layouts} - * of a suitable carrier. The mapping between a scalar type and its corresponding layout is dependent on the ABI - * implemented by the native linker. For instance, the C type {@code long} maps to the layout constant - * {@link ValueLayout#JAVA_LONG} on Linux/x64, but maps to the layout constant {@link ValueLayout#JAVA_INT} on - * Windows/x64. Similarly, the C type {@code size_t} maps to the layout constant {@link ValueLayout#JAVA_LONG} - * on 64-bit platforms, but maps to the layout constant {@link ValueLayout#JAVA_INT} on 32-bit platforms. + * of a suitable carrier. The {@linkplain #canonicalLayouts() mapping} between a scalar type and its corresponding + * canonical layout is dependent on the ABI implemented by the native linker (see below). *

    * Composite types are modelled as {@linkplain GroupLayout group layouts}. More specifically, a C {@code struct} type * maps to a {@linkplain StructLayout struct layout}, whereas a C {@code union} type maps to a {@link UnionLayout union @@ -123,7 +123,33 @@ * a pointer that is known to point to a C {@code int[2]} array can be modelled as an address layout whose * target layout is a sequence layout whose element count is 2, and whose element type is {@link ValueLayout#JAVA_INT}. *

    - * The following table shows some examples of how C types are modelled in Linux/x64: + * All native linker implementations are guaranteed to provide canonical layouts for the following set of types: + *

      + *
    • {@code bool}
    • + *
    • {@code char}
    • + *
    • {@code short}
    • + *
    • {@code int}
    • + *
    • {@code long}
    • + *
    • {@code long long}
    • + *
    • {@code float}
    • + *
    • {@code double}
    • + *
    • {@code size_t}
    • + *
    • {@code wchar_t}
    • + *
    • {@code void*}
    • + *
    + * As noted above, the specific canonical layout associated with each type can vary, depending on the data model + * supported by a given ABI. For instance, the C type {@code long} maps to the layout constant {@link ValueLayout#JAVA_LONG} + * on Linux/x64, but maps to the layout constant {@link ValueLayout#JAVA_INT} on Windows/x64. Similarly, the C type + * {@code size_t} maps to the layout constant {@link ValueLayout#JAVA_LONG} on 64-bit platforms, but maps to the layout + * constant {@link ValueLayout#JAVA_INT} on 32-bit platforms. + *

    + * A native linker typically does not provide canonical layouts for C's unsigned integral types. Instead, they are + * modelled using the canonical layouts associated with their corresponding signed integral types. For instance, + * the C type {@code unsigned long} maps to the layout constant {@link ValueLayout#JAVA_LONG} on Linux/x64, but maps to + * the layout constant {@link ValueLayout#JAVA_INT} on Windows/x64. + *

    + * The following table shows some examples of how C types are modelled in Linux/x64 according to the + * "System V Application Binary Interface" (all the examples provided here will assume these platform-dependent mappings): * *

    * @@ -138,19 +164,19 @@ * * * - * + * * * - * + * * * - * + * * * - * + * * * - * + * * * * @@ -201,20 +227,7 @@ * All native linker implementations operate on a subset of memory layouts. More formally, a layout {@code L} * is supported by a native linker {@code NL} if: *
      - *
    • {@code L} is a value layout {@code V} and {@code V.withoutName()} is {@linkplain MemoryLayout#equals(Object) equal} - * to one of the following layout constants: - *
        - *
      • {@link ValueLayout#JAVA_BOOLEAN}
      • - *
      • {@link ValueLayout#JAVA_BYTE}
      • - *
      • {@link ValueLayout#JAVA_CHAR}
      • - *
      • {@link ValueLayout#JAVA_SHORT}
      • - *
      • {@link ValueLayout#JAVA_INT}
      • - *
      • {@link ValueLayout#JAVA_LONG}
      • - *
      • {@link ValueLayout#JAVA_FLOAT}
      • - *
      • {@link ValueLayout#JAVA_DOUBLE}
      • - *
    • - *
    • {@code L} is an address layout {@code A} and {@code A.withoutTargetLayout().withoutName()} is - * {@linkplain MemoryLayout#equals(Object) equal} to {@link ValueLayout#ADDRESS}
    • + *
    • {@code L} is a value layout {@code V} and {@code V.withoutName()} is a canonical layout
    • *
    • {@code L} is a sequence layout {@code S} and all the following conditions hold: *
        *
      1. the alignment constraint of {@code S} is set to its natural alignment, and
      2. @@ -294,7 +307,7 @@ * {@snippet lang = java: * try (Arena arena = Arena.ofConfined()) { * MemorySegment comparFunc = linker.upcallStub(comparHandle, comparDesc, arena); - * MemorySegment array = arena.allocateArray(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7); + * MemorySegment array = arena.allocateFrom(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7); * qsort.invokeExact(array, 10L, 4L, comparFunc); * int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] * } @@ -391,15 +404,11 @@ * *

        Variadic functions

        * - * Variadic functions are C functions which can accept a variable number and type of arguments. They are declared: - *
          - *
        1. With a trailing ellipsis ({@code ...}) at the end of the formal parameter list, such as: {@code void foo(int x, ...);}
        2. - *
        3. With an empty formal parameter list, called a prototype-less function, such as: {@code void foo();}
        4. - *
        - * The arguments passed in place of the ellipsis, or the arguments passed to a prototype-less function are called - * variadic arguments. Variadic functions are, essentially, templates that can be specialized into multiple - * non-variadic functions by replacing the {@code ...} or empty formal parameter list with a list of variadic parameters - * of a fixed number and type. + * Variadic functions are C functions which can accept a variable number and type of arguments. They are declared with a + * trailing ellipsis ({@code ...}) at the end of the formal parameter list, such as: {@code void foo(int x, ...);} + * The arguments passed in place of the ellipsis are called variadic arguments. Variadic functions are, + * essentially, templates that can be specialized into multiple non-variadic functions by replacing the + * {@code ...} with a list of variadic parameters of a fixed number and type. *

        * It should be noted that values passed as variadic arguments undergo default argument promotion in C. For instance, the * following argument promotions are applied: @@ -411,21 +420,22 @@ *

    * whereby the signed-ness of the source type corresponds to the signed-ness of the promoted type. The complete process * of default argument promotion is described in the C specification. In effect these promotions place limits on the - * specialized form of a variadic function, as the variadic parameters of the specialized form will always have a promoted - * type. + * types that can be used to replace the {@code ...}, as the variadic parameters of the specialized form of a variadic + * function will always have a promoted type. *

    * The native linker only supports linking the specialized form of a variadic function. A variadic function in its specialized * form can be linked using a function descriptor describing the specialized form. Additionally, the * {@link Linker.Option#firstVariadicArg(int)} linker option must be provided to indicate the first variadic parameter in * the parameter list. The corresponding argument layout (if any), and all following argument layouts in the specialized - * function descriptor, are called variadic argument layouts. For a prototype-less function, the index passed to - * {@link Linker.Option#firstVariadicArg(int)} should always be {@code 0}. + * function descriptor, are called variadic argument layouts. *

    - * The native linker will reject an attempt to link a specialized function descriptor with any variadic argument layouts - * corresponding to a C type that would be subject to default argument promotion (as described above). Exactly which layouts - * will be rejected is platform specific, but as an example: on Linux/x64 the layouts {@link ValueLayout#JAVA_BOOLEAN}, - * {@link ValueLayout#JAVA_BYTE}, {@link ValueLayout#JAVA_CHAR}, {@link ValueLayout#JAVA_SHORT}, and - * {@link ValueLayout#JAVA_FLOAT} will be rejected. + * The native linker does not automatically perform default argument promotions. However, since passing an argument of a + * non-promoted type as a variadic argument is not supported in C, the native linker will reject an attempt to link a + * specialized function descriptor with any variadic argument value layouts corresponding to a non-promoted C type. + * Since the size of the C {@code int} type is platform-specific, exactly which layouts will be rejected is + * platform-specific as well. As an example: on Linux/x64 the layouts corresponding to the C types {@code _Bool}, + * {@code (unsigned) char}, {@code (unsigned) short}, and {@code float} (among others), will be rejected by the linker. + * The {@link #canonicalLayouts()} method can be used to find which layout corresponds to a particular C type. *

    * A well-known variadic function is the {@code printf} function, defined in the C standard library: * @@ -461,9 +471,9 @@ * * {@snippet lang = java: * try (Arena arena = Arena.ofConfined()) { - * int res = (int)printf.invokeExact(arena.allocateUtf8String("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4" - * } + * int res = (int)printf.invokeExact(arena.allocateFrom("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4" * } + *} * *

    Safety considerations

    * @@ -483,9 +493,8 @@ * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. * - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface Linker permits AbstractLinker { /** @@ -493,11 +502,11 @@ public sealed interface Linker permits AbstractLinker { * is the combination of OS and processor where the Java runtime is currently executing. * * @apiNote It is not currently possible to obtain a linker for a different combination of OS and processor. + * @implSpec A native linker implementation is guaranteed to provide canonical layouts for + * basic C types. * @implNote The libraries exposed by the {@linkplain #defaultLookup() default lookup} associated with the returned * linker are the native libraries loaded in the process where the Java runtime is currently executing. For example, * on Linux, these libraries typically include {@code libc}, {@code libm} and {@code libdl}. - * - * @throws UnsupportedOperationException if the underlying native platform is not supported. */ static Linker nativeLinker() { return SharedUtils.getSystemLinker(); @@ -513,8 +522,7 @@ static Linker nativeLinker() { *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @param address the native memory segment whose {@linkplain MemorySegment#address() base address} is the * address of the target foreign function. @@ -560,13 +568,17 @@ static Linker nativeLinker() { * {@code T}, then the size of the returned segment is set to {@code T.byteSize()}. *

    * The returned method handle will throw an {@link IllegalArgumentException} if the {@link MemorySegment} - * representing the target address of the foreign function is the {@link MemorySegment#NULL} address. - * The returned method handle will additionally throw {@link NullPointerException} if any argument passed to it is {@code null}. + * representing the target address of the foreign function is the {@link MemorySegment#NULL} address. If an argument + * is a {@link MemorySegment}, whose corresponding layout is a {@linkplain GroupLayout group layout}, the linker + * might attempt to access the contents of the segment. As such, one of the exceptions specified by the + * {@link MemorySegment#get(ValueLayout.OfByte, long)} or the + * {@link MemorySegment#copy(MemorySegment, long, MemorySegment, long, long)} methods may be thrown. + * The returned method handle will additionally throw {@link NullPointerException} if any argument + * passed to it is {@code null}. *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @param function the function descriptor of the target foreign function. * @param options the linker options associated with this linkage request. @@ -603,8 +615,7 @@ static Linker nativeLinker() { *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @param target the target method handle. * @param function the upcall stub function descriptor. @@ -639,11 +650,26 @@ static Linker nativeLinker() { */ SymbolLookup defaultLookup(); + /** + * {@return an unmodifiable mapping between the names of data types used by the ABI implemented by this linker and their + * canonical layouts} + *

    + * Each {@link Linker} is responsible for choosing the data types that are widely recognized as useful on the OS + * and processor combination supported by the {@link Linker}. Accordingly, the precise set of data type names + * and canonical layouts exposed by the linker is unspecified; it varies from one {@link Linker} to another. + * @implNote It is strongly recommended that the result of {@link #canonicalLayouts()} exposes a set of symbols that is stable over time. + * Clients of {@link #canonicalLayouts()} are likely to fail if a data type that was previously exposed by the linker + * is no longer exposed, or if its canonical layout is updated. + *

    If an implementer provides {@link Linker} implementations for multiple OS and processor combinations, then it is strongly + * recommended that the result of {@link #canonicalLayouts()} exposes, as much as possible, a consistent set of symbols + * across all the OS and processor combinations. + */ + Map canonicalLayouts(); + /** * A linker option is used to provide additional parameters to a linkage request. - * @since 20 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) sealed interface Option permits LinkerOptions.LinkerOptionImpl { @@ -707,6 +733,8 @@ static Option firstVariadicArg(int index) { * // use errno * } * } + *

    + * This linker option can not be combined with {@link #critical}. * * @param capturedState the names of the values to save. * @throws IllegalArgumentException if at least one of the provided {@code capturedState} names @@ -750,19 +778,19 @@ static StructLayout captureStateLayout() { } /** - * {@return a linker option used to mark a foreign function as trivial} + * {@return a linker option used to mark a foreign function as critical} *

    - * A trivial function is a function that has an extremely short running time - * in all cases (similar to calling an empty function), and does not call back into Java (e.g. using an upcall stub). + * A critical function is a function that has an extremely short running time in all cases + * (similar to calling an empty function), and does not call back into Java (e.g. using an upcall stub). *

    * Using this linker option is a hint which some implementations may use to apply - * optimizations that are only valid for trivial functions. + * optimizations that are only valid for critical functions. *

    - * Using this linker option when linking non trivial functions is likely to have adverse effects, + * Using this linker option when linking non-critical functions is likely to have adverse effects, * such as loss of performance, or JVM crashes. */ - static Option isTrivial() { - return LinkerOptions.IsTrivial.INSTANCE; + static Option critical() { + return LinkerOptions.Critical.INSTANCE; } } } diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java index c36bb2c3454..635caff6776 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java @@ -27,6 +27,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.util.EnumSet; import java.util.Objects; @@ -43,12 +44,12 @@ import jdk.internal.foreign.layout.SequenceLayoutImpl; import jdk.internal.foreign.layout.StructLayoutImpl; import jdk.internal.foreign.layout.UnionLayoutImpl; -import jdk.internal.javac.PreviewFeature; +import jdk.internal.vm.annotation.ForceInline; /** * A memory layout describes the contents of a memory segment. *

    - * There are two leaves in the layout hierarchy, {@linkplain ValueLayout value layouts}, which are used to represent values of given size and kind (see + * There are two leaves in the layout hierarchy, {@linkplain ValueLayout value layouts}, which are used to represent values of given size and kind * and {@linkplain PaddingLayout padding layouts} which are used, as the name suggests, to represent a portion of a memory * segment whose contents should be ignored, and which are primarily present for alignment reasons. * Some common value layout constants, such as {@link ValueLayout#JAVA_INT} and {@link ValueLayout#JAVA_FLOAT_UNALIGNED} @@ -231,13 +232,49 @@ * Any attempt to provide a layout path {@code P} that is not well-formed for an initial layout {@code C_0} will result * in an {@link IllegalArgumentException}. * + *

    Access mode restrictions

    + * + * A var handle returned by {@link #varHandle(PathElement...)} or {@link ValueLayout#varHandle()} features certain + * access characteristics, which are derived from the selected layout {@code L}: + *
      + *
    • A carrier type {@code T}, derived from {@code L.carrier()}
    • + *
    • An alignment constraint {@code A}, derived from {@code L.byteAlignment()}
    • + *
    • An access size {@code S}, derived from {@code L.byteSize()}
    • + *
    + * Depending on the above characteristics, the returned var handle might feature certain access mode restrictions. + * We say that a var handle is aligned if its alignment constraint {@code A} is compatible with the access size + * {@code S}, that is if {@code A >= S}. An aligned var handle is guaranteed to support the following access modes: + *
      + *
    • read write access modes for all {@code T}. On 32-bit platforms, access modes + * {@code get} and {@code set} for {@code long}, {@code double} and {@code MemorySegment} + * are supported but might lead to word tearing, as described in Section {@jls 17.7}. + * of The Java Language Specification. + *
    • atomic update access modes for {@code int}, {@code long}, + * {@code float}, {@code double} and {@link MemorySegment}. + * (Future major platform releases of the JDK may support additional + * types for certain currently unsupported access modes.) + *
    • numeric atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}. + * (Future major platform releases of the JDK may support additional + * numeric types for certain currently unsupported access modes.) + *
    • bitwise atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}. + * (Future major platform releases of the JDK may support additional + * numeric types for certain currently unsupported access modes.) + *
    + * If {@code T} is {@code float}, {@code double} or {@link MemorySegment} then atomic update access modes compare + * values using their bitwise representation (see {@link Float#floatToRawIntBits}, {@link Double#doubleToRawLongBits} + * and {@link MemorySegment#address()}, respectively). + *

    + * Alternatively, a var handle is unaligned if its alignment constraint {@code A} is incompatible with the + * access size {@code S}, that is, if {@code A < S}. An unaligned var handle only supports the {@code get} and {@code set} + * access modes. All other access modes will result in {@link UnsupportedOperationException} being thrown. Moreover, + * while supported, access modes {@code get} and {@code set} might lead to word tearing. + * * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. * * @sealedGraph - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, PaddingLayout, ValueLayout { /** @@ -292,6 +329,44 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin */ MemoryLayout withByteAlignment(long byteAlignment); + /** + * {@return {@code offset + (byteSize() * index)}} + * + * @param offset the base offset + * @param index the index to be scaled by the byte size of this layout + * @throws IllegalArgumentException if {@code offset} or {@code index} is negative + * @throws ArithmeticException if either the addition or multiplication overflows + */ + @ForceInline + default long scale(long offset, long index) { + if (offset < 0) { + throw new IllegalArgumentException("Negative offset: " + offset); + } + if (index < 0) { + throw new IllegalArgumentException("Negative index: " + index); + } + + return Math.addExact(offset, Math.multiplyExact(byteSize(), index)); + } + + /** + *{@return a method handle that can be used to invoke {@link #scale(long, long)} on this layout} + */ + default MethodHandle scaleHandle() { + class Holder { + static final MethodHandle MH_SCALE; + static { + try { + MH_SCALE = MethodHandles.lookup().findVirtual(MemoryLayout.class, "scale", + MethodType.methodType(long.class, long.class, long.class)); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } + } + return Holder.MH_SCALE.bindTo(this); + } + /** * Computes the offset, in bytes, of the layout selected by the given layout path, where the initial layout in the * path is this layout. @@ -314,7 +389,8 @@ default long byteOffset(PathElement... elements) { * The returned method handle has the following characteristics: *

      *
    • its return type is {@code long};
    • - *
    • it has as zero or more parameters of type {@code long}, one for each open path element + *
    • it has one leading {@code long} parameter representing the base offset;
    • + *
    • it has as zero or more trailing parameters of type {@code long}, one for each open path element * in the provided layout path. The order of these parameters corresponds to the order in which the open path * elements occur in the provided layout path. *
    @@ -322,13 +398,14 @@ default long byteOffset(PathElement... elements) { * The final offset returned by the method handle is computed as follows: * *
    {@code
    -     * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = b + c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
          * }
    * - * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} - * arguments, whereas {@code c_1}, {@code c_2}, ... {@code c_m} are static offset constants - * and {@code s_0}, {@code s_1}, ... {@code s_n} are static stride constants which are derived from - * the layout path. + * where {@code b} represents the base offset provided as a dynamic {@code long} argument, {@code x_1}, {@code x_2}, + * ... {@code x_n} represent indices into sequences provided as dynamic {@code long} arguments, whereas + * {@code s_1}, {@code s_2}, ... {@code s_n} are static stride constants derived from the size of the element + * layout of a sequence, and {@code c_1}, {@code c_2}, ... {@code c_m} are other static offset constants + * (such as field offsets) which are derived from the layout path. * * @apiNote The returned method handle can be used to compute a layout offset, similarly to {@link #byteOffset(PathElement...)}, * but more flexibly, as some indices can be specified when invoking the method handle. @@ -351,71 +428,93 @@ default MethodHandle byteOffsetHandle(PathElement... elements) { *
      *
    • its type is derived from the {@linkplain ValueLayout#carrier() carrier} of the * selected value layout;
    • - *
    • it has as zero or more access coordinates of type {@code long}, one for each - * open path element in the provided layout path. The order of these access - * coordinates corresponds to the order in which the open path elements occur in the provided - * layout path. + *
    • it has a leading parameter of type {@code MemorySegment} representing the accessed segment
    • + *
    • a following {@code long} parameter, corresponding to the base offset, denoted as {@code B};
    • + *
    • it has zero or more trailing access coordinates of type {@code long}, one for each + * open path element in the provided layout path, denoted as + * {@code I1, I2, ... In}, respectively. The order of these access coordinates corresponds to the order + * in which the open path elements occur in the provided layout path. *
    *

    - * The final address accessed by the returned var handle can be computed as follows: - * - *

    {@code
    -     * address = base(segment) + offset
    -     * }
    - * - * Where {@code base(segment)} denotes a function that returns the physical base address of the accessed - * memory segment. For native segments, this function just returns the native segment's - * {@linkplain MemorySegment#address() address}. For heap segments, this function is more complex, as the address - * of heap segments is virtualized. The {@code offset} value can be expressed in the following form: - * - *
    {@code
    -     * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    -     * }
    + * If the provided layout path {@code P} contains no dereference elements, then the offset {@code O} of the access + * operation is computed as follows: * - * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} - * arguments, whereas {@code c_1}, {@code c_2}, ... {@code c_m} are static offset constants - * and {@code s_1}, {@code s_2}, ... {@code s_n} are static stride constants which are derived from - * the layout path. + * {@snippet lang = "java": + * O = this.offsetHandle(P).invokeExact(B, I1, I2, ... In); + * } *

    - * Additionally, the provided dynamic values must conform to bounds which are derived from the layout path, that is, - * {@code 0 <= x_i < b_i}, where {@code 1 <= i <= n}, or {@link IndexOutOfBoundsException} is thrown. + * Accessing a memory segment using the var handle returned by this method is subject to the following checks: + *

      + *
    • The physical address of the accessed memory segment must be aligned + * according to the {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout), or + * an {@link IllegalArgumentException} will be issued. Note that the alignment constraint of the root layout + * can be more strict (but not less) than the alignment constraint of the selected value layout.
    • + *
    • The offset of the access operation (computed as above) must fall inside the spatial bounds of the + * accessed memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case when {@code O + A <= S}, + * where {@code O} is the accessed offset (computed as above), {@code A} is the size of the selected layout and {@code S} + * is the size of the accessed memory segment.
    • + *
    • The accessed memory segment must be {@link MemorySegment#isAccessibleBy(Thread) accessible} from the + * thread performing the access operation, or a {@link WrongThreadException} is thrown.
    • + *
    • The {@linkplain MemorySegment#scope() scope} associated with the accessed segment must be + * {@linkplain MemorySegment.Scope#isAlive() alive}, or an {@link IllegalStateException} is thrown.
    • + *
    *

    - * The base address must be aligned according to the {@linkplain - * #byteAlignment() alignment constraint} of the root layout (this layout). Note that this can be more strict - * (but not less) than the alignment constraint of the selected value layout. + * If the selected layout is an {@linkplain AddressLayout address layout}, calling {@link VarHandle#get(Object...)} + * on the returned var handle will return a new memory segment. The segment is associated with a fresh scope that is + * always alive. Moreover, the size of the segment depends on whether the address layout has a + * {@linkplain AddressLayout#targetLayout() target layout}. More specifically: + *

      + *
    • If the address layout has a target layout {@code T}, then the size of the returned segment + * is {@code T.byteSize()};
    • + *
    • Otherwise, the address layout has no target layout, and the size of the returned segment + * is zero.
    • + *
    + * Moreover, if the selected layout is an {@linkplain AddressLayout address layout}, calling {@link VarHandle#set(Object...)} + * can throw {@link IllegalArgumentException} if the memory segment representing the address to be written is not a + * {@linkplain MemorySegment#isNative() native} memory segment. *

    - * Multiple paths can be chained, with dereference path elements. - * A dereference path element constructs a fresh native memory segment whose base address is the address value - * read obtained by accessing a memory segment at the offset determined by the layout path elements immediately preceding - * the dereference path element. In other words, if a layout path contains one or more dereference path elements, - * the final address accessed by the returned var handle can be computed as follows: - * - *

    {@code
    -     * address_1 = base(segment) + offset_1
    -     * address_2 = base(segment_1) + offset_2
    -     * ...
    -     * address_k = base(segment_k-1) + offset_k
    -     * }
    + * If the provided layout path has size {@code m} and contains a dereference path element in position {@code k} + * (where {@code k <= m}) then two layout paths {@code P} and {@code P'} are derived, where P contains all the path + * elements from 0 to {@code k - 1} and {@code P'} contains all the path elements from {@code k + 1} to + * {@code m} (if any). Then, the returned var handle is computed as follows: + * + * {@snippet lang = "java": + * VarHandle baseHandle = this.varHandle(P); + * MemoryLayout target = ((AddressLayout)this.select(P)).targetLayout().get(); + * VarHandle targetHandle = target.varHandle(P'); + * targetHandle = MethodHandles.insertCoordinates(targetHandle, 1, 0L); // always access nested targets at offset 0 + * targetHandle = MethodHandles.collectCoordinates(targetHandle, 0, + * baseHandle.toMethodHandle(VarHandle.AccessMode.GET)); + * } * - * where {@code k} is the number of dereference path elements in a layout path, {@code segment} is the input segment, - * {@code segment_1}, ... {@code segment_k-1} are the segments obtained by dereferencing the address associated with - * a given dereference path element (e.g. {@code segment_1} is a native segment whose base address is {@code address_1}), - * and {@code offset_1}, {@code offset_2}, ... {@code offset_k} are the offsets computed by evaluating - * the path elements after a given dereference operation (these offsets are obtained using the computation described - * above). In these more complex access operations, all memory accesses immediately preceding a dereference operation - * (e.g. those at addresses {@code address_1}, {@code address_2}, ..., {@code address_k-1} are performed using the - * {@link VarHandle.AccessMode#GET} access mode. + * (The above can be trivially generalized to cases where the provided layout path contains more than one dereference + * path elements). + *

    + * As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows: + * {@snippet lang = "java": + * GroupLayout grp = java.lang.foreign.MemoryLayout.structLayout( + * MemoryLayout.paddingLayout(4), + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value") + * ); + * } + * To access the member layout named {@code value}, we can construct a var handle as follows: + * {@snippet lang = "java": + * VarHandle handle = grp.varHandle(PathElement.groupElement("value")); //(MemorySegment, long) -> int + * } * - * @apiNote The resulting var handle features certain access mode restrictions, which are common to all - * {@linkplain MethodHandles#memorySegmentViewVarHandle(ValueLayout) memory segment view handles}. + * @apiNote The resulting var handle features certain access mode restrictions, + * which are common to all var handles derived from memory layouts. * * @param elements the layout path elements. * @return a var handle that accesses a memory segment at the offset selected by the given layout path. * @throws IllegalArgumentException if the layout path is not well-formed for this layout. * @throws IllegalArgumentException if the layout selected by the provided path is not a {@linkplain ValueLayout value layout}. - * @see MethodHandles#memorySegmentViewVarHandle(ValueLayout) */ default VarHandle varHandle(PathElement... elements) { + Objects.requireNonNull(elements); + if (this instanceof ValueLayout vl && elements.length == 0) { + return vl.varHandle(); // fast path + } return computePathOp(LayoutPath.rootPath(this), LayoutPath::dereferenceHandle, Set.of(), elements); } @@ -427,23 +526,27 @@ default VarHandle varHandle(PathElement... elements) { * The returned method handle has the following characteristics: *

      *
    • its return type is {@code MemorySegment};
    • - *
    • it has a leading parameter of type {@code MemorySegment}, corresponding to the memory segment - * to be sliced;
    • - *
    • it has as zero or more parameters of type {@code long}, one for each open path element + *
    • it has a leading parameter of type {@code MemorySegment} corresponding to the memory segment to be sliced
    • + *
    • a following {@code long} parameter, corresponding to the base offset
    • + *
    • it has as zero or more trailing parameters of type {@code long}, one for each open path element * in the provided layout path. The order of these parameters corresponds to the order in which the open path * elements occur in the provided layout path. *
    *

    - * The offset of the returned segment is computed as follows: - * {@snippet lang=java : - * long offset = byteOffset(elements); - * long size = select(elements).byteSize(); - * MemorySegment slice = segment.asSlice(offset, size); - * } + * The offset {@code O} of the returned segment is computed as if by a call to a + * {@linkplain #byteOffsetHandle(PathElement...) byte offset handle} constructed using the given path elements. *

    - * The segment to be sliced must be aligned according to the - * {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout). Note that this can be more - * strict (but not less) than the alignment constraint of the selected value layout. + * Computing a slice of a memory segment using the method handle returned by this method is subject to the following checks: + *

      + *
    • The physical address of the accessed memory segment must be aligned + * according to the {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout), or + * an {@link IllegalArgumentException} will be issued. Note that the alignment constraint of the root layout + * can be more strict (but not less) than the alignment constraint of the selected layout.
    • + *
    • The start offset of the slicing operation (computed as above) must fall fall inside the spatial bounds of the + * accessed memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case when {@code O + A <= S}, + * where {@code O} is the start offset of the slicing operation (computed as above), {@code A} is the size of the + * selected layout and {@code S} is the size of the accessed memory segment.
    • + *
    * * @apiNote The returned method handle can be used to obtain a memory segment slice, similarly to {@link MemorySegment#asSlice(long, long)}, * but more flexibly, as some indices can be specified when invoking the method handle. @@ -501,9 +604,8 @@ private static Z computePathOp(LayoutPath path, Function fina * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. * - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) sealed interface PathElement permits LayoutPath.PathElementImpl { /** @@ -669,24 +771,6 @@ static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayo SequenceLayoutImpl.of(elementCount, elementLayout)); } - /** - * Creates a sequence layout with the given element layout and the maximum element - * count such that it does not overflow a {@code long}. - * - * This is equivalent to the following code: - * {@snippet lang = java: - * sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout); - * } - * - * @param elementLayout the sequence element layout. - * @return a new sequence layout with the given element layout and maximum element count. - * @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}. - */ - static SequenceLayout sequenceLayout(MemoryLayout elementLayout) { - Objects.requireNonNull(elementLayout); - return sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout); - } - /** * Creates a struct layout with the given member layouts. * diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index f648354df60..11beb471695 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -26,15 +26,13 @@ package java.lang.foreign; import java.io.UncheckedIOException; -import java.lang.foreign.Linker.Option; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.channels.FileChannel; -import java.nio.channels.FileChannel.*; +import java.nio.channels.FileChannel.MapMode; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Objects; @@ -46,10 +44,8 @@ import jdk.internal.foreign.HeapMemorySegmentImpl; import jdk.internal.foreign.MemorySessionImpl; import jdk.internal.foreign.NativeMemorySegmentImpl; +import jdk.internal.foreign.StringSupport; import jdk.internal.foreign.Utils; -import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.foreign.layout.ValueLayouts; -import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.Restricted; import jdk.internal.reflect.CallerSensitive; import jdk.internal.vm.annotation.ForceInline; @@ -128,32 +124,47 @@ * int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); * } * - * For more complex access operations (e.g. structured memory access), clients can obtain a - * {@linkplain MethodHandles#memorySegmentViewVarHandle(ValueLayout) var handle} - * that accepts a segment and a {@code long} offset. More complex var handles - * can be obtained by adapting a segment var handle view using the var handle combinator functions defined in the - * {@link java.lang.invoke.MethodHandles} class: + * More complex access operations can be implemented using var handles. The {@link ValueLayout#varHandle()} + * method can be used to obtain a var handle that can be used to get/set values represented by the given value layout on a memory segment. + * A var handle obtained from a layout supports several additional + * access modes. More importantly, var handles can be combined with method handles to express complex access + * operations. For instance, a var handle that can be used to access an element of an {@code int} array at a given logical + * index can be created as follows: * - * {@snippet lang=java : + * {@snippet lang=java: * MemorySegment segment = ... - * VarHandle intHandle = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT); - * MethodHandle multiplyExact = MethodHandles.lookup() - * .findStatic(Math.class, "multiplyExact", - * MethodType.methodType(long.class, long.class, long.class)); - * intHandle = MethodHandles.filterCoordinates(intHandle, 1, - * MethodHandles.insertArguments(multiplyExact, 0, ValueLayout.JAVA_INT.byteSize())); - * int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12 + * VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); // (MemorySegment, long) + * MethodHandle scale = ValueLayout.JAVA_INT.scaleHandle(); // + * JAVA_INT.byteSize() + * + * intHandle = MethodHandles.filterCoordinates(intHandle, 1, scale); + * int value = (int) intHandle.get(segment, 0L, 3L); // get int element at offset 0 + 3 * 4 = 12 * } * - * Alternatively, complex var handles can can be obtained - * from {@linkplain MemoryLayout#varHandle(MemoryLayout.PathElement...) memory layouts} - * by providing a so called layout path: + * To make the process of creating these var handles easier, the method + * {@link MemoryLayout#varHandle(MemoryLayout.PathElement...)} can be used, by providing it a so called + * layout path. A layout path, consisting of several layout + * path elements, selects a value layout to be accessed, which can be nested inside another memory layout. For example, + * we can express the access to an element of an {@code int} array using layout paths like so: * * {@snippet lang=java : * MemorySegment segment = ... - * VarHandle intHandle = ValueLayout.JAVA_INT.arrayElementVarHandle(); - * int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12 + * MemoryLayout segmentLayout = MemoryLayout.structLayout( + * ValueLayout.JAVA_INT.withName("size"), + * MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT).withName("data") // array of 4 elements + * ); + * VarHandle intHandle = segmentLayout.varHandle(MemoryLayout.PathElement.groupElement("data"), + * MemoryLayout.PathElement.sequenceElement()); + * int value = (int) intHandle.get(segment, 0L, 3L); // get int element at offset 0 + offsetof(data) + 3 * 4 = 12 * } + * Where {@code offsetof(data)} is the offset of the {@code data} element layout of the {@code segmentLayout} layout + * + * Both the var handle returned by {@link ValueLayout#varHandle()} and + * {@link MemoryLayout#varHandle(MemoryLayout.PathElement...)}, as well as the method handle returned by + * {@link MemoryLayout#byteOffsetHandle(MemoryLayout.PathElement...)} and {@link MemoryLayout#sliceHandle(MemoryLayout.PathElement...)} + * feature a base offset parameter. This parameter represents a base offset for the offset computation. This + * parameter allows a client to combine these handles further with additional offset computations. This is demonstrated + * in the first of the two examples above, where {@code intHandle} is combined with a + * {@linkplain MemoryLayout#scaleHandle() scale handle} obtained from {@code ValueLayout.JAVA_INT}. * *

    Slicing memory segments

    * @@ -434,9 +445,8 @@ * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. * - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface MemorySegment permits AbstractMemorySegmentImpl { /** @@ -597,8 +607,7 @@ default MemorySegment asSlice(long offset, MemoryLayout layout) { *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @param newSize the size of the returned segment. * @return a new memory segment that has the same address and scope as this segment, but the new @@ -631,8 +640,7 @@ default MemorySegment asSlice(long offset, MemoryLayout layout) { *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @apiNote The cleanup action (if present) should take care not to leak the received segment to external * clients which might access the segment after its backing region of memory is no longer available. Furthermore, @@ -671,8 +679,7 @@ default MemorySegment asSlice(long offset, MemoryLayout layout) { *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @apiNote The cleanup action (if present) should take care not to leak the received segment to external * clients which might access the segment after its backing region of memory is no longer available. Furthermore, @@ -739,30 +746,6 @@ default MemorySegment asSlice(long offset, MemoryLayout layout) { */ Optional asOverlappingSlice(MemorySegment other); - /** - * Returns the offset, in bytes, of the provided segment, relative to this - * segment. - * - *

    The offset is relative to the address of this segment and can be - * a negative or positive value. For instance, if both segments are native - * segments, or heap segments backed by the same array, the resulting offset - * can be computed as follows: - * - * {@snippet lang=java : - * other.address() - address() - * } - * - * If the segments share the same address, {@code 0} is returned. If - * {@code other} is a slice of this segment, the offset is always - * {@code 0 <= x < this.byteSize()}. - * - * @param other the segment to retrieve an offset to. - * @throws UnsupportedOperationException if the two segments cannot be compared, e.g. because they are of - * different kinds, or because they are backed by different Java arrays. - * @return the relative offset, in bytes, of the provided segment. - */ - long segmentOffset(MemorySegment other); - /** * Fills the contents of this memory segment with the given value. *

    @@ -771,7 +754,7 @@ default MemorySegment asSlice(long offset, MemoryLayout layout) { * * {@snippet lang=java : * for (long offset = 0; offset < segment.byteSize(); offset++) { - * byteHandle.set(ValueLayout.JAVA_BYTE, offset, value); + * segment.set(ValueLayout.JAVA_BYTE, offset, value); * } * } * @@ -1072,52 +1055,123 @@ default long mismatch(MemorySegment other) { double[] toArray(ValueLayout.OfDouble elementLayout); /** - * Reads a UTF-8 encoded, null-terminated string from this segment at the given offset. + * Reads a null-terminated string from this segment at the given offset, using the + * {@linkplain StandardCharsets#UTF_8 UTF-8} charset. *

    - * This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. + * Calling this method is equivalent to the following code: + * {@snippet lang = java: + * getString(offset, StandardCharsets.UTF_8); + *} + * * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @return a Java string constructed from the bytes read from the given starting address up to (but not including) * the first {@code '\0'} terminator character (assuming one is found). - * @throws IllegalArgumentException if the size of the UTF-8 string is greater than the largest string supported by the platform. - * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code offset > byteSize() - S}, where {@code S} is the size of the UTF-8 - * string (including the terminator character). + * @throws IllegalArgumentException if the size of the string is greater than the largest string supported by the platform. + * @throws IndexOutOfBoundsException if {@code offset < 0}. + * @throws IndexOutOfBoundsException if {@code offset > byteSize() - (B + 1)}, where {@code B} is the size, + * in bytes, of the string encoded using UTF-8 charset {@code str.getBytes(StandardCharsets.UTF_8).length}). * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. */ - default String getUtf8String(long offset) { - return SharedUtils.toJavaStringInternal(this, offset); + default String getString(long offset) { + return getString(offset, StandardCharsets.UTF_8); } /** - * Writes the given string into this segment at the given offset, converting it to a null-terminated byte sequence using UTF-8 encoding. + * Reads a null-terminated string from this segment at the given offset, using the provided charset. *

    * This method always replaces malformed-input and unmappable-character * sequences with this charset's default replacement string. The {@link * java.nio.charset.CharsetDecoder} class should be used when more control * over the decoding process is required. + * + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @param charset the charset used to {@linkplain Charset#newDecoder() decode} the string bytes. + * @return a Java string constructed from the bytes read from the given starting address up to (but not including) + * the first {@code '\0'} terminator character (assuming one is found). + * @throws IllegalArgumentException if the size of the string is greater than the largest string supported by the platform. + * @throws IndexOutOfBoundsException if {@code offset < 0}. + * @throws IndexOutOfBoundsException if {@code offset > byteSize() - (B + N)}, where: + *

      + *
    • {@code B} is the size, in bytes, of the string encoded using the provided charset + * (e.g. {@code str.getBytes(charset).length});
    • + *
    • {@code N} is the size (in bytes) of the terminator char according to the provided charset. For instance, + * this is 1 for {@link StandardCharsets#US_ASCII} and 2 for {@link StandardCharsets#UTF_16}.
    • + *
    + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain Scope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if {@code charset} is not a {@linkplain StandardCharsets standard charset}. + */ + default String getString(long offset, Charset charset) { + Objects.requireNonNull(charset); + return StringSupport.read(this, offset, charset); + } + + /** + * Writes the given string into this segment at the given offset, converting it to a null-terminated byte sequence + * using the {@linkplain StandardCharsets#UTF_8 UTF-8} charset. *

    - * If the given string contains any {@code '\0'} characters, they will be - * copied as well. This means that, depending on the method used to read - * the string, such as {@link MemorySegment#getUtf8String(long)}, the string - * will appear truncated when read again. + * Calling this method is equivalent to the following code: + * {@snippet lang = java: + * setString(offset, str, StandardCharsets.UTF_8); + *} * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * the final address of this write operation can be expressed as {@code address() + offset}. * @param str the Java string to be written into this segment. - * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code offset > byteSize() - str.getBytes().length() + 1}. + * @throws IndexOutOfBoundsException if {@code offset < 0}. + * @throws IndexOutOfBoundsException if {@code offset > byteSize() - (B + 1)}, where {@code B} is the size, + * in bytes, of the string encoded using UTF-8 charset {@code str.getBytes(StandardCharsets.UTF_8).length}). * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not * {@linkplain Scope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. */ - default void setUtf8String(long offset, String str) { - Utils.toCString(str.getBytes(StandardCharsets.UTF_8), SegmentAllocator.prefixAllocator(asSlice(offset))); + default void setString(long offset, String str) { + Objects.requireNonNull(str); + setString(offset, str, StandardCharsets.UTF_8); } + /** + * Writes the given string into this segment at the given offset, converting it to a null-terminated byte sequence + * using the provided charset. + *

    + * This method always replaces malformed-input and unmappable-character + * sequences with this charset's default replacement string. The {@link + * java.nio.charset.CharsetDecoder} class should be used when more control + * over the decoding process is required. + *

    + * If the given string contains any {@code '\0'} characters, they will be + * copied as well. This means that, depending on the method used to read + * the string, such as {@link MemorySegment#getString(long)}, the string + * will appear truncated when read again. + * + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * the final address of this write operation can be expressed as {@code address() + offset}. + * @param str the Java string to be written into this segment. + * @param charset the charset used to {@linkplain Charset#newEncoder() encode} the string bytes. + * @throws IndexOutOfBoundsException if {@code offset < 0}. + * @throws IndexOutOfBoundsException if {@code offset > byteSize() - (B + N)}, where: + *

      + *
    • {@code B} is the size, in bytes, of the string encoded using the provided charset + * (e.g. {@code str.getBytes(charset).length});
    • + *
    • {@code N} is the size (in bytes) of the terminator char according to the provided charset. For instance, + * this is 1 for {@link StandardCharsets#US_ASCII} and 2 for {@link StandardCharsets#UTF_16}.
    • + *
    + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain Scope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if {@code charset} is not a {@linkplain StandardCharsets standard charset}. + */ + default void setString(long offset, String str, Charset charset) { + Objects.requireNonNull(charset); + Objects.requireNonNull(str); + StringSupport.write(this, offset, charset, str); + } /** * Creates a memory segment that is backed by the same region of memory that backs the given {@link Buffer} instance. @@ -1281,8 +1335,9 @@ static MemorySegment ofAddress(long address) { * {@linkplain Scope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code dstSegment.isAccessibleBy(T) == false}. - * @throws IndexOutOfBoundsException if {@code srcOffset > srcSegment.byteSize() - bytes} or if - * {@code dstOffset > dstSegment.byteSize() - bytes}, or if either {@code srcOffset}, {@code dstOffset} + * @throws IndexOutOfBoundsException if {@code srcOffset > srcSegment.byteSize() - bytes}. + * @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - bytes}. + * @throws IndexOutOfBoundsException if either {@code srcOffset}, {@code dstOffset} * or {@code bytes} are {@code < 0}. * @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}. */ @@ -1320,17 +1375,21 @@ static void copy(MemorySegment srcSegment, long srcOffset, * @param elementCount the number of elements to be copied. * @throws IllegalArgumentException if the element layouts have different sizes, if the source (resp. destination) segment/offset are * incompatible with the alignment constraint in the source - * (resp. destination) element layout, or if the source (resp. destination) element layout alignment is greater than its size. + * (resp. destination) element layout. + * @throws IllegalArgumentException if {@code srcElementLayout.byteAlignment() > srcElementLayout.byteSize()}. + * @throws IllegalArgumentException if {@code dstElementLayout.byteAlignment() > dstElementLayout.byteSize()}. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code srcSegment} is not * {@linkplain Scope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, - * such that {@code srcSegment().isAccessibleBy(T) == false}. + * such that {@code srcSegment.isAccessibleBy(T) == false}. * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code dstSegment} is not * {@linkplain Scope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, - * such that {@code dstSegment().isAccessibleBy(T) == false}. + * such that {@code dstSegment.isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if {@code dstSegment} is {@linkplain #isReadOnly() read-only}. - * @throws IndexOutOfBoundsException if {@code elementCount * srcLayout.byteSize()} or {@code elementCount * dtsLayout.byteSize()} overflows. + * @throws IndexOutOfBoundsException if {@code elementCount * srcLayout.byteSize()} overflows. + * @throws IndexOutOfBoundsException if {@code elementCount * dtsLayout.byteSize()} overflows. + * @throws IndexOutOfBoundsException if {@code srcOffset > srcSegment.byteSize() - (elementCount * srcLayout.byteSize())}. * @throws IndexOutOfBoundsException if {@code dstOffset > dstSegment.byteSize() - (elementCount * dstLayout.byteSize())}. * @throws IndexOutOfBoundsException if either {@code srcOffset}, {@code dstOffset} or {@code elementCount} are {@code < 0}. */ @@ -1361,7 +1420,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr */ @ForceInline default byte get(ValueLayout.OfByte layout, long offset) { - return (byte) ((ValueLayouts.OfByteImpl) layout).accessHandle().get(this, offset); + return (byte) layout.varHandle().get(this, offset); } /** @@ -1381,7 +1440,7 @@ default byte get(ValueLayout.OfByte layout, long offset) { */ @ForceInline default void set(ValueLayout.OfByte layout, long offset, byte value) { - ((ValueLayouts.OfByteImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1400,7 +1459,7 @@ default void set(ValueLayout.OfByte layout, long offset, byte value) { */ @ForceInline default boolean get(ValueLayout.OfBoolean layout, long offset) { - return (boolean) ((ValueLayouts.OfBooleanImpl) layout).accessHandle().get(this, offset); + return (boolean) layout.varHandle().get(this, offset); } /** @@ -1420,7 +1479,7 @@ default boolean get(ValueLayout.OfBoolean layout, long offset) { */ @ForceInline default void set(ValueLayout.OfBoolean layout, long offset, boolean value) { - ((ValueLayouts.OfBooleanImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1439,7 +1498,7 @@ default void set(ValueLayout.OfBoolean layout, long offset, boolean value) { */ @ForceInline default char get(ValueLayout.OfChar layout, long offset) { - return (char) ((ValueLayouts.OfCharImpl) layout).accessHandle().get(this, offset); + return (char) layout.varHandle().get(this, offset); } /** @@ -1459,7 +1518,7 @@ default char get(ValueLayout.OfChar layout, long offset) { */ @ForceInline default void set(ValueLayout.OfChar layout, long offset, char value) { - ((ValueLayouts.OfCharImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1478,7 +1537,7 @@ default void set(ValueLayout.OfChar layout, long offset, char value) { */ @ForceInline default short get(ValueLayout.OfShort layout, long offset) { - return (short) ((ValueLayouts.OfShortImpl) layout).accessHandle().get(this, offset); + return (short) layout.varHandle().get(this, offset); } /** @@ -1498,7 +1557,7 @@ default short get(ValueLayout.OfShort layout, long offset) { */ @ForceInline default void set(ValueLayout.OfShort layout, long offset, short value) { - ((ValueLayouts.OfShortImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1517,7 +1576,7 @@ default void set(ValueLayout.OfShort layout, long offset, short value) { */ @ForceInline default int get(ValueLayout.OfInt layout, long offset) { - return (int) ((ValueLayouts.OfIntImpl) layout).accessHandle().get(this, offset); + return (int) layout.varHandle().get(this, offset); } /** @@ -1537,7 +1596,7 @@ default int get(ValueLayout.OfInt layout, long offset) { */ @ForceInline default void set(ValueLayout.OfInt layout, long offset, int value) { - ((ValueLayouts.OfIntImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1556,7 +1615,7 @@ default void set(ValueLayout.OfInt layout, long offset, int value) { */ @ForceInline default float get(ValueLayout.OfFloat layout, long offset) { - return (float)((ValueLayouts.OfFloatImpl) layout).accessHandle().get(this, offset); + return (float)layout.varHandle().get(this, offset); } /** @@ -1576,7 +1635,7 @@ default float get(ValueLayout.OfFloat layout, long offset) { */ @ForceInline default void set(ValueLayout.OfFloat layout, long offset, float value) { - ((ValueLayouts.OfFloatImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1595,7 +1654,7 @@ default void set(ValueLayout.OfFloat layout, long offset, float value) { */ @ForceInline default long get(ValueLayout.OfLong layout, long offset) { - return (long) ((ValueLayouts.OfLongImpl) layout).accessHandle().get(this, offset); + return (long) layout.varHandle().get(this, offset); } /** @@ -1615,7 +1674,7 @@ default long get(ValueLayout.OfLong layout, long offset) { */ @ForceInline default void set(ValueLayout.OfLong layout, long offset, long value) { - ((ValueLayouts.OfLongImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1634,7 +1693,7 @@ default void set(ValueLayout.OfLong layout, long offset, long value) { */ @ForceInline default double get(ValueLayout.OfDouble layout, long offset) { - return (double) ((ValueLayouts.OfDoubleImpl) layout).accessHandle().get(this, offset); + return (double) layout.varHandle().get(this, offset); } /** @@ -1654,7 +1713,7 @@ default double get(ValueLayout.OfDouble layout, long offset) { */ @ForceInline default void set(ValueLayout.OfDouble layout, long offset, double value) { - ((ValueLayouts.OfDoubleImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1679,7 +1738,7 @@ default void set(ValueLayout.OfDouble layout, long offset, double value) { */ @ForceInline default MemorySegment get(AddressLayout layout, long offset) { - return (MemorySegment) ((ValueLayouts.OfAddressImpl) layout).accessHandle().get(this, offset); + return (MemorySegment) layout.varHandle().get(this, offset); } /** @@ -1700,7 +1759,7 @@ default MemorySegment get(AddressLayout layout, long offset) { */ @ForceInline default void set(AddressLayout layout, long offset, MemorySegment value) { - ((ValueLayouts.OfAddressImpl) layout).accessHandle().set(this, offset, value); + layout.varHandle().set(this, offset, value); } /** @@ -1715,8 +1774,8 @@ default void set(AddressLayout layout, long offset, MemorySegment value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -1724,7 +1783,7 @@ default void set(AddressLayout layout, long offset, MemorySegment value) { default byte getAtIndex(ValueLayout.OfByte layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (byte) ((ValueLayouts.OfByteImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (byte) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -1739,8 +1798,8 @@ default byte getAtIndex(ValueLayout.OfByte layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -1748,7 +1807,7 @@ default byte getAtIndex(ValueLayout.OfByte layout, long index) { default boolean getAtIndex(ValueLayout.OfBoolean layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (boolean) ((ValueLayouts.OfBooleanImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (boolean) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -1763,8 +1822,8 @@ default boolean getAtIndex(ValueLayout.OfBoolean layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -1772,7 +1831,7 @@ default boolean getAtIndex(ValueLayout.OfBoolean layout, long index) { default char getAtIndex(ValueLayout.OfChar layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (char) ((ValueLayouts.OfCharImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (char) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -1787,8 +1846,8 @@ default char getAtIndex(ValueLayout.OfChar layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1797,7 +1856,7 @@ default char getAtIndex(ValueLayout.OfChar layout, long index) { default void setAtIndex(ValueLayout.OfChar layout, long index, char value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfCharImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -1812,8 +1871,8 @@ default void setAtIndex(ValueLayout.OfChar layout, long index, char value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -1821,7 +1880,7 @@ default void setAtIndex(ValueLayout.OfChar layout, long index, char value) { default short getAtIndex(ValueLayout.OfShort layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (short) ((ValueLayouts.OfShortImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (short) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -1836,8 +1895,8 @@ default short getAtIndex(ValueLayout.OfShort layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1846,7 +1905,7 @@ default short getAtIndex(ValueLayout.OfShort layout, long index) { default void setAtIndex(ValueLayout.OfByte layout, long index, byte value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfByteImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } @@ -1862,8 +1921,8 @@ default void setAtIndex(ValueLayout.OfByte layout, long index, byte value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1872,7 +1931,7 @@ default void setAtIndex(ValueLayout.OfByte layout, long index, byte value) { default void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfBooleanImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -1887,8 +1946,8 @@ default void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value) * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1897,7 +1956,7 @@ default void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value) default void setAtIndex(ValueLayout.OfShort layout, long index, short value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfShortImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -1912,8 +1971,8 @@ default void setAtIndex(ValueLayout.OfShort layout, long index, short value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -1921,7 +1980,7 @@ default void setAtIndex(ValueLayout.OfShort layout, long index, short value) { default int getAtIndex(ValueLayout.OfInt layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (int) ((ValueLayouts.OfIntImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (int) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -1936,8 +1995,8 @@ default int getAtIndex(ValueLayout.OfInt layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1946,7 +2005,7 @@ default int getAtIndex(ValueLayout.OfInt layout, long index) { default void setAtIndex(ValueLayout.OfInt layout, long index, int value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfIntImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -1961,8 +2020,8 @@ default void setAtIndex(ValueLayout.OfInt layout, long index, int value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -1970,7 +2029,7 @@ default void setAtIndex(ValueLayout.OfInt layout, long index, int value) { default float getAtIndex(ValueLayout.OfFloat layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (float) ((ValueLayouts.OfFloatImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (float) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -1985,8 +2044,8 @@ default float getAtIndex(ValueLayout.OfFloat layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -1995,7 +2054,7 @@ default float getAtIndex(ValueLayout.OfFloat layout, long index) { default void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfFloatImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -2010,8 +2069,8 @@ default void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -2019,7 +2078,7 @@ default void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { default long getAtIndex(ValueLayout.OfLong layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (long) ((ValueLayouts.OfLongImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (long) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -2034,8 +2093,8 @@ default long getAtIndex(ValueLayout.OfLong layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -2044,7 +2103,7 @@ default long getAtIndex(ValueLayout.OfLong layout, long index) { default void setAtIndex(ValueLayout.OfLong layout, long index, long value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfLongImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -2059,8 +2118,8 @@ default void setAtIndex(ValueLayout.OfLong layout, long index, long value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. */ @@ -2068,7 +2127,7 @@ default void setAtIndex(ValueLayout.OfLong layout, long index, long value) { default double getAtIndex(ValueLayout.OfDouble layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (double) ((ValueLayouts.OfDoubleImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (double) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -2083,8 +2142,8 @@ default double getAtIndex(ValueLayout.OfDouble layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -2093,7 +2152,7 @@ default double getAtIndex(ValueLayout.OfDouble layout, long index) { default void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfDoubleImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -2111,8 +2170,8 @@ default void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IllegalArgumentException if provided address layout has a {@linkplain AddressLayout#targetLayout() target layout} * {@code T}, and the address of the returned segment * incompatible with the alignment constraint in {@code T}. @@ -2123,7 +2182,7 @@ default void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { default MemorySegment getAtIndex(AddressLayout layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (MemorySegment) ((ValueLayouts.OfAddressImpl) layout).accessHandle().get(this, index * layout.byteSize()); + return (MemorySegment) layout.varHandle().get(this, index * layout.byteSize()); } /** @@ -2138,8 +2197,8 @@ default MemorySegment getAtIndex(AddressLayout layout, long index) { * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code isAccessibleBy(T) == false}. * @throws IllegalArgumentException if the access operation is - * incompatible with the alignment constraint in the provided layout, - * or if the layout alignment is greater than its size. + * incompatible with the alignment constraint in the provided layout. + * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}. * @throws IndexOutOfBoundsException if {@code index * byteSize()} overflows. * @throws IndexOutOfBoundsException if {@code index * byteSize() > byteSize() - layout.byteSize()}. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. @@ -2149,7 +2208,7 @@ default MemorySegment getAtIndex(AddressLayout layout, long index) { default void setAtIndex(AddressLayout layout, long index, MemorySegment value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - ((ValueLayouts.OfAddressImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); + layout.varHandle().set(this, index * layout.byteSize(), value); } /** @@ -2198,7 +2257,7 @@ default void setAtIndex(AddressLayout layout, long index, MemorySegment value) { * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code srcSegment} is not * {@linkplain Scope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, - * such that {@code srcSegment().isAccessibleBy(T) == false}. + * such that {@code srcSegment.isAccessibleBy(T) == false}. * @throws IllegalArgumentException if {@code dstArray} is not an array, or if it is an array but whose type is not supported. * @throws IllegalArgumentException if the destination array component type does not match {@code srcLayout.carrier()}. * @throws IllegalArgumentException if {@code offset} is incompatible @@ -2237,7 +2296,7 @@ static void copy( * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code dstSegment} is not * {@linkplain Scope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, - * such that {@code dstSegment().isAccessibleBy(T) == false}. + * such that {@code dstSegment.isAccessibleBy(T) == false}. * @throws IllegalArgumentException if {@code srcArray} is not an array, or if it is an array but whose type is not supported. * @throws IllegalArgumentException if the source array component type does not match {@code srcLayout.carrier()}. * @throws IllegalArgumentException if {@code offset} is incompatible @@ -2312,7 +2371,6 @@ static long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOff * Scope instances can be compared for equality. That is, two scopes * are considered {@linkplain #equals(Object)} if they denote the same lifetime. */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) sealed interface Scope permits MemorySessionImpl { /** * {@return {@code true}, if the regions of memory backing the memory segments associated with this scope are diff --git a/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java b/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java index 0df705999e3..921ef9c8479 100644 --- a/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java @@ -26,7 +26,6 @@ package java.lang.foreign; import jdk.internal.foreign.layout.PaddingLayoutImpl; -import jdk.internal.javac.PreviewFeature; /** * A padding layout. A padding layout specifies the size of extra space which is typically not accessed by applications, @@ -35,9 +34,8 @@ * @implSpec * Implementing classes are immutable, thread-safe and value-based. * - * @since 20 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface PaddingLayout extends MemoryLayout permits PaddingLayoutImpl { /** diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java index b659e32fa8a..8d411cdc4ca 100644 --- a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java +++ b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java @@ -25,16 +25,15 @@ package java.lang.foreign; -import java.lang.invoke.VarHandle; -import java.lang.reflect.Array; -import java.nio.ByteOrder; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Objects; -import java.util.function.Function; + import jdk.internal.foreign.AbstractMemorySegmentImpl; +import jdk.internal.foreign.ArenaImpl; import jdk.internal.foreign.SlicingAllocator; -import jdk.internal.foreign.Utils; -import jdk.internal.javac.PreviewFeature; +import jdk.internal.foreign.StringSupport; +import jdk.internal.vm.annotation.ForceInline; /** * An object that may be used to allocate {@linkplain MemorySegment memory segments}. Clients implementing this interface @@ -70,14 +69,32 @@ * Clients should consider using an {@linkplain Arena arena} instead, which, provides strong thread-safety, * lifetime and non-overlapping guarantees. * - * @since 19 + * @since 22 */ @FunctionalInterface -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public interface SegmentAllocator { /** - * {@return a new memory segment with a Java string converted into a UTF-8 encoded, null-terminated C string} + * Converts a Java string into a null-terminated C string using the {@linkplain StandardCharsets#UTF_8 UTF-8} charset, + * storing the result into a memory segment. + *

    + * Calling this method is equivalent to the following code: + * {@snippet lang = java: + * allocateFrom(str, StandardCharsets.UTF_8); + *} + * + * @param str the Java string to be converted into a C string. + * @return a new native segment containing the converted C string. + */ + @ForceInline + default MemorySegment allocateFrom(String str) { + Objects.requireNonNull(str); + return allocateFrom(str, StandardCharsets.UTF_8); + } + + /** + * Converts a Java string into a null-terminated C string using the provided charset, + * and storing the result into a memory segment. *

    * This method always replaces malformed-input and unmappable-character * sequences with this charset's default replacement byte array. The @@ -86,21 +103,42 @@ public interface SegmentAllocator { *

    * If the given string contains any {@code '\0'} characters, they will be * copied as well. This means that, depending on the method used to read - * the string, such as {@link MemorySegment#getUtf8String(long)}, the string + * the string, such as {@link MemorySegment#getString(long)}, the string * will appear truncated when read again. * + * @param str the Java string to be converted into a C string. + * @param charset the charset used to {@linkplain Charset#newEncoder() encode} the string bytes. + * @return a new native segment containing the converted C string. + * @throws IllegalArgumentException if {@code charset} is not a {@linkplain StandardCharsets standard charset}. * @implSpec The default implementation for this method copies the contents of the provided Java string - * into a new memory segment obtained by calling {@code this.allocate(str.length() + 1)}. - * @param str the Java string to be converted into a C string. + * into a new memory segment obtained by calling {@code this.allocate(B + N)}, where: + *

      + *
    • {@code B} is the size, in bytes, of the string encoded using the provided charset + * (e.g. {@code str.getBytes(charset).length});
    • + *
    • {@code N} is the size (in bytes) of the terminator char according to the provided charset. For instance, + * this is 1 for {@link StandardCharsets#US_ASCII} and 2 for {@link StandardCharsets#UTF_16}.
    • + *
    */ - default MemorySegment allocateUtf8String(String str) { + @ForceInline + default MemorySegment allocateFrom(String str, Charset charset) { + Objects.requireNonNull(charset); Objects.requireNonNull(str); - return Utils.toCString(str.getBytes(StandardCharsets.UTF_8), this); + int termCharSize = StringSupport.CharsetKind.of(charset).terminatorCharSize(); + byte[] bytes = str.getBytes(charset); + MemorySegment segment = allocateNoInit(bytes.length + termCharSize); + MemorySegment.copy(bytes, 0, segment, ValueLayout.JAVA_BYTE, 0, bytes.length); + for (int i = 0 ; i < termCharSize ; i++) { + segment.set(ValueLayout.JAVA_BYTE, bytes.length + i, (byte)0); + } + return segment; } /** - * {@return a new memory segment initialized with the provided {@code byte} {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the provided byte value.} + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -112,17 +150,19 @@ default MemorySegment allocateUtf8String(String str) { * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. */ - default MemorySegment allocate(ValueLayout.OfByte layout, byte value) { + default MemorySegment allocateFrom(ValueLayout.OfByte layout, byte value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(); - MemorySegment seg = allocate(layout); - handle.set(seg, value); + MemorySegment seg = allocateNoInit(layout); + seg.set(layout, 0, value); return seg; } /** - * {@return a new memory segment initialized with the provided {@code char} {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the provided char value.} + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -134,17 +174,19 @@ default MemorySegment allocate(ValueLayout.OfByte layout, byte value) { * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. */ - default MemorySegment allocate(ValueLayout.OfChar layout, char value) { + default MemorySegment allocateFrom(ValueLayout.OfChar layout, char value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(); - MemorySegment seg = allocate(layout); - handle.set(seg, value); + MemorySegment seg = allocateNoInit(layout); + seg.set(layout, 0, value); return seg; } /** - * {@return a new memory segment initialized with the provided {@code short} {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the provided short value.} + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -156,17 +198,19 @@ default MemorySegment allocate(ValueLayout.OfChar layout, char value) { * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. */ - default MemorySegment allocate(ValueLayout.OfShort layout, short value) { + default MemorySegment allocateFrom(ValueLayout.OfShort layout, short value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(); - MemorySegment seg = allocate(layout); - handle.set(seg, value); + MemorySegment seg = allocateNoInit(layout); + seg.set(layout, 0, value); return seg; } /** - * {@return a new memory segment initialized with the provided {@code int} {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the provided int value.} + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -178,17 +222,19 @@ default MemorySegment allocate(ValueLayout.OfShort layout, short value) { * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. */ - default MemorySegment allocate(ValueLayout.OfInt layout, int value) { + default MemorySegment allocateFrom(ValueLayout.OfInt layout, int value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(); - MemorySegment seg = allocate(layout); - handle.set(seg, value); + MemorySegment seg = allocateNoInit(layout); + seg.set(layout, 0, value); return seg; } /** - * {@return a new memory segment initialized with the provided {@code float} {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the provided float value.} + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -200,17 +246,19 @@ default MemorySegment allocate(ValueLayout.OfInt layout, int value) { * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. */ - default MemorySegment allocate(ValueLayout.OfFloat layout, float value) { + default MemorySegment allocateFrom(ValueLayout.OfFloat layout, float value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(); - MemorySegment seg = allocate(layout); - handle.set(seg, value); + MemorySegment seg = allocateNoInit(layout); + seg.set(layout, 0, value); return seg; } /** - * {@return a new memory segment initialized with the provided {@code long} {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the provided long value.} + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -222,17 +270,19 @@ default MemorySegment allocate(ValueLayout.OfFloat layout, float value) { * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. */ - default MemorySegment allocate(ValueLayout.OfLong layout, long value) { + default MemorySegment allocateFrom(ValueLayout.OfLong layout, long value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(); - MemorySegment seg = allocate(layout); - handle.set(seg, value); + MemorySegment seg = allocateNoInit(layout); + seg.set(layout, 0, value); return seg; } /** - * {@return a new memory segment initialized with the provided {@code double} {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the provided double value.} + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -244,19 +294,21 @@ default MemorySegment allocate(ValueLayout.OfLong layout, long value) { * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. */ - default MemorySegment allocate(ValueLayout.OfDouble layout, double value) { + default MemorySegment allocateFrom(ValueLayout.OfDouble layout, double value) { Objects.requireNonNull(layout); - VarHandle handle = layout.varHandle(); - MemorySegment seg = allocate(layout); - handle.set(seg, value); + MemorySegment seg = allocateNoInit(layout); + seg.set(layout, 0, value); return seg; } /** - * {@return a new memory segment initialized with the address of the provided {@code value} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} + * {@return a new memory segment initialized with the {@linkplain MemorySegment#address() address} of the provided memory segment.} *

    * The address value might be narrowed according to the platform address size (see {@link ValueLayout#ADDRESS}). + *

    + * The size of the allocated memory segment is the {@linkplain MemoryLayout#byteSize() size} of the given layout. + * The given value is written into the segment according to the byte order and alignment constraint of the + * given layout. * * @implSpec The default implementation is equivalent to: * {@snippet lang=java : @@ -268,164 +320,210 @@ default MemorySegment allocate(ValueLayout.OfDouble layout, double value) { * * @param layout the layout of the block of memory to be allocated. * @param value the value to be set in the newly allocated memory segment. + * @throws UnsupportedOperationException if {@code value} is not a {@linkplain MemorySegment#isNative() native} segment. */ - default MemorySegment allocate(AddressLayout layout, MemorySegment value) { + default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) { Objects.requireNonNull(value); Objects.requireNonNull(layout); - MemorySegment seg = allocate(layout); - layout.varHandle().set(seg, value); - return seg; + MemorySegment segment = allocateNoInit(layout); + segment.set(layout, 0, value); + return segment; } /** - * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of - * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code byte} {@code elements} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} - * - * @implSpec The default implementation is equivalent to: - * {@snippet lang=java : - * int size = Objects.requireNonNull(elements).length; - * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); - * return seg; + * {@return a new memory segment initialized with the contents of the provided segment.} + *

    + * The size of the allocated memory segment is the {@code elementLayout.byteSize() * elementCount}. + * The contents of the source segment is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * MemorySegment dest = this.allocate(elementLayout, elementCount); + * MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount); + * return dest; * } - * - * @param elementLayout the element layout of the array to be allocated. - * @param elements the short elements to be copied to the newly allocated memory block. + * @param elementLayout the element layout of the allocated array. + * @param source the source segment. + * @param sourceElementLayout the element layout of the source segment. + * @param sourceOffset the starting offset, in bytes, of the source segment. + * @param elementCount the number of elements in the source segment to be copied. + * @throws IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()}. + * @throws IllegalArgumentException if the source segment/offset are incompatible with the alignment constraint + * in the source element layout. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. + * @throws IllegalArgumentException if {@code sourceElementLayout.byteAlignment() > sourceElementLayout.byteSize()}. + * @throws IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated with {@code source} is not + * {@linkplain MemorySegment.Scope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code source.isAccessibleBy(T) == false}. + * @throws IndexOutOfBoundsException if {@code elementCount * sourceElementLayout.byteSize()} overflows. + * @throws IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}. + * @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0}. */ - default MemorySegment allocateArray(ValueLayout.OfByte elementLayout, byte... elements) { - return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); + @ForceInline + default MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source, + ValueLayout sourceElementLayout, long sourceOffset, long elementCount) { + Objects.requireNonNull(source); + Objects.requireNonNull(sourceElementLayout); + Objects.requireNonNull(elementLayout); + MemorySegment dest = allocateNoInit(elementLayout, elementCount); + MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount); + return dest; } /** - * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of - * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code short} {@code elements} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} - * - * @implSpec The default implementation is equivalent to: - * {@snippet lang=java : - * int size = Objects.requireNonNull(elements).length; - * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); - * return seg; - * } - * + * {@return a new memory segment initialized with the elements in the provided byte array.} + *

    + * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. + * The contents of the source array is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * this.allocateFrom(layout, MemorySegment.ofArray(array), + * ValueLayout.JAVA_BYTE, 0, array.length) + *} * @param elementLayout the element layout of the array to be allocated. - * @param elements the short elements to be copied to the newly allocated memory block. + * @param elements the byte elements to be copied to the newly allocated memory block. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. */ - default MemorySegment allocateArray(ValueLayout.OfShort elementLayout, short... elements) { - return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); + @ForceInline + default MemorySegment allocateFrom(ValueLayout.OfByte elementLayout, byte... elements) { + return allocateFrom(elementLayout, MemorySegment.ofArray(elements), + ValueLayout.JAVA_BYTE, 0, elements.length); } /** - * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of - * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code char} {@code elements} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} - * - * @implSpec The default implementation is equivalent to: - * {@snippet lang=java : - * int size = Objects.requireNonNull(elements).length; - * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); - * return seg; - * } - * + * {@return a new memory segment initialized with the elements in the provided short array.} + *

    + * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. + * The contents of the source array is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * this.allocateFrom(layout, MemorySegment.ofArray(array), + * ValueLayout.JAVA_SHORT, 0, array.length) + *} * @param elementLayout the element layout of the array to be allocated. * @param elements the short elements to be copied to the newly allocated memory block. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. */ - default MemorySegment allocateArray(ValueLayout.OfChar elementLayout, char... elements) { - return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); + @ForceInline + default MemorySegment allocateFrom(ValueLayout.OfShort elementLayout, short... elements) { + return allocateFrom(elementLayout, MemorySegment.ofArray(elements), + ValueLayout.JAVA_SHORT, 0, elements.length); } /** - * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of - * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code int} {@code elements} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} - * - * @implSpec The default implementation is equivalent to: - * {@snippet lang=java : - * int size = Objects.requireNonNull(elements).length; - * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); - * return seg; - * } - * + * {@return a new memory segment initialized with the elements in the provided char array.} + *

    + * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. + * The contents of the source array is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * this.allocateFrom(layout, MemorySegment.ofArray(array), + * ValueLayout.JAVA_CHAR, 0, array.length) + *} * @param elementLayout the element layout of the array to be allocated. - * @param elements the short elements to be copied to the newly allocated memory block. + * @param elements the char elements to be copied to the newly allocated memory block. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. */ - default MemorySegment allocateArray(ValueLayout.OfInt elementLayout, int... elements) { - return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); + @ForceInline + default MemorySegment allocateFrom(ValueLayout.OfChar elementLayout, char... elements) { + return allocateFrom(elementLayout, MemorySegment.ofArray(elements), + ValueLayout.JAVA_CHAR, 0, elements.length); } /** - * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of - * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code float} {@code elements} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} - * - * @implSpec The default implementation is equivalent to: - * {@snippet lang=java : - * int size = Objects.requireNonNull(elements).length; - * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); - * return seg; - * } - * + * {@return a new memory segment initialized with the elements in the provided int array.} + *

    + * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. + * The contents of the source array is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * this.allocateFrom(layout, MemorySegment.ofArray(array), + * ValueLayout.JAVA_INT, 0, array.length) + *} * @param elementLayout the element layout of the array to be allocated. - * @param elements the short elements to be copied to the newly allocated memory block. + * @param elements the int elements to be copied to the newly allocated memory block. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. */ - default MemorySegment allocateArray(ValueLayout.OfFloat elementLayout, float... elements) { - return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); + @ForceInline + default MemorySegment allocateFrom(ValueLayout.OfInt elementLayout, int... elements) { + return allocateFrom(elementLayout, MemorySegment.ofArray(elements), + ValueLayout.JAVA_INT, 0, elements.length); } /** - * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of - * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code long} {@code elements} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} - * - * @implSpec The default implementation is equivalent to: - * {@snippet lang=java : - * int size = Objects.requireNonNull(elements).length; - * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); - * return seg; - * } - * + * {@return a new memory segment initialized with the elements in the provided float array.} + *

    + * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. + * The contents of the source array is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * this.allocateFrom(layout, MemorySegment.ofArray(array), + * ValueLayout.JAVA_FLOAT, 0, array.length) + *} * @param elementLayout the element layout of the array to be allocated. - * @param elements the short elements to be copied to the newly allocated memory block. + * @param elements the float elements to be copied to the newly allocated memory block. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. */ - default MemorySegment allocateArray(ValueLayout.OfLong elementLayout, long... elements) { - return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); + @ForceInline + default MemorySegment allocateFrom(ValueLayout.OfFloat elementLayout, float... elements) { + return allocateFrom(elementLayout, MemorySegment.ofArray(elements), + ValueLayout.JAVA_FLOAT, 0, elements.length); } /** - * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of - * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code double} {@code elements} as - * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} - * - * @implSpec The default implementation is equivalent to: - * {@snippet lang=java : - * int size = Objects.requireNonNull(elements).length; - * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); - * return seg; - * } - * + * {@return a new memory segment initialized with the elements in the provided long array.} + *

    + * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. + * The contents of the source array is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * this.allocateFrom(layout, MemorySegment.ofArray(array), + * ValueLayout.JAVA_LONG, 0, array.length) + *} * @param elementLayout the element layout of the array to be allocated. - * @param elements the short elements to be copied to the newly allocated memory block. + * @param elements the long elements to be copied to the newly allocated memory block. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. */ - default MemorySegment allocateArray(ValueLayout.OfDouble elementLayout, double... elements) { - return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); + @ForceInline + default MemorySegment allocateFrom(ValueLayout.OfLong elementLayout, long... elements) { + return allocateFrom(elementLayout, MemorySegment.ofArray(elements), + ValueLayout.JAVA_LONG, 0, elements.length); } - private MemorySegment copyArrayWithSwapIfNeeded(Z array, ValueLayout elementLayout, - Function heapSegmentFactory) { - int size = Array.getLength(Objects.requireNonNull(array)); - MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); - if (size > 0) { - MemorySegment.copy(heapSegmentFactory.apply(array), elementLayout, 0, - seg, elementLayout.withOrder(ByteOrder.nativeOrder()), 0, size); - } - return seg; + /** + * {@return a new memory segment initialized with the elements in the provided double array.} + *

    + * The size of the allocated memory segment is {@code elementLayout.byteSize() * elements.length}. + * The contents of the source array is copied into the result segment element by element, according to the byte + * order and alignment constraint of the given element layout. + * + * @implSpec the default implementation for this method is equivalent to the following code: + * {@snippet lang = java: + * this.allocateFrom(layout, MemorySegment.ofArray(array), + * ValueLayout.JAVA_DOUBLE, 0, array.length) + *} + * @param elementLayout the element layout of the array to be allocated. + * @param elements the double elements to be copied to the newly allocated memory block. + * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}. + */ + @ForceInline + default MemorySegment allocateFrom(ValueLayout.OfDouble elementLayout, double... elements) { + return allocateFrom(elementLayout, MemorySegment.ofArray(elements), + ValueLayout.JAVA_DOUBLE, 0, elements.length); } /** @@ -452,7 +550,7 @@ default MemorySegment allocate(MemoryLayout layout) { * @throws IllegalArgumentException if {@code elementLayout.byteSize() * count} overflows. * @throws IllegalArgumentException if {@code count < 0}. */ - default MemorySegment allocateArray(MemoryLayout elementLayout, long count) { + default MemorySegment allocate(MemoryLayout elementLayout, long count) { Objects.requireNonNull(elementLayout); if (count < 0) { throw new IllegalArgumentException("Negative array size"); @@ -525,4 +623,25 @@ static SegmentAllocator slicingAllocator(MemorySegment segment) { static SegmentAllocator prefixAllocator(MemorySegment segment) { return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment); } + + @ForceInline + private MemorySegment allocateNoInit(long byteSize) { + return this instanceof ArenaImpl arenaImpl ? + arenaImpl.allocateNoInit(byteSize, 1) : + allocate(byteSize); + } + + @ForceInline + private MemorySegment allocateNoInit(MemoryLayout layout) { + return this instanceof ArenaImpl arenaImpl ? + arenaImpl.allocateNoInit(layout.byteSize(), layout.byteAlignment()) : + allocate(layout); + } + + @ForceInline + private MemorySegment allocateNoInit(MemoryLayout layout, long size) { + return this instanceof ArenaImpl arenaImpl ? + arenaImpl.allocateNoInit(layout.byteSize() * size, layout.byteAlignment()) : + allocate(layout, size); + } } diff --git a/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java b/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java index c08b5ef4a8d..16384f4ac6c 100644 --- a/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java @@ -26,7 +26,6 @@ package java.lang.foreign; import jdk.internal.foreign.layout.SequenceLayoutImpl; -import jdk.internal.javac.PreviewFeature; /** * A compound layout that denotes a homogeneous repetition of a given element layout. @@ -50,9 +49,8 @@ * @implSpec * This class is immutable, thread-safe and value-based. * - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface SequenceLayout extends MemoryLayout permits SequenceLayoutImpl { diff --git a/src/java.base/share/classes/java/lang/foreign/StructLayout.java b/src/java.base/share/classes/java/lang/foreign/StructLayout.java index 81421ff5acf..c0800bb6b1c 100644 --- a/src/java.base/share/classes/java/lang/foreign/StructLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/StructLayout.java @@ -26,7 +26,6 @@ package java.lang.foreign; import jdk.internal.foreign.layout.StructLayoutImpl; -import jdk.internal.javac.PreviewFeature; /** * A group layout whose member layouts are laid out one after the other. @@ -34,9 +33,8 @@ * @implSpec * Implementing classes are immutable, thread-safe and value-based. * - * @since 20 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface StructLayout extends GroupLayout permits StructLayoutImpl { /** diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java index 616d0336a0f..aafe44b4d40 100644 --- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java +++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java @@ -29,7 +29,6 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.foreign.MemorySessionImpl; import jdk.internal.foreign.Utils; -import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.Restricted; import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.NativeLibrary; @@ -120,9 +119,8 @@ * MemorySegment malloc = stdlib.find("malloc").orElseThrow(); *} * - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) @FunctionalInterface public interface SymbolLookup { @@ -216,8 +214,7 @@ static SymbolLookup loaderLookup() { *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @implNote The process of resolving a library name is OS-specific. For instance, in a POSIX-compliant OS, * the library name is resolved according to the specification of the {@code dlopen} function for that OS. @@ -251,8 +248,7 @@ static SymbolLookup libraryLookup(String name, Arena arena) { *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. + * the JVM or, worse, silently result in memory corruption. * * @implNote On Linux, the functionalities provided by this factory method and the returned symbol lookup are * implemented using the {@code dlopen}, {@code dlsym} and {@code dlclose} functions. diff --git a/src/java.base/share/classes/java/lang/foreign/UnionLayout.java b/src/java.base/share/classes/java/lang/foreign/UnionLayout.java index 8d0048aee4c..ddd33aeeba5 100644 --- a/src/java.base/share/classes/java/lang/foreign/UnionLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/UnionLayout.java @@ -26,7 +26,6 @@ package java.lang.foreign; import jdk.internal.foreign.layout.UnionLayoutImpl; -import jdk.internal.javac.PreviewFeature; /** * A group layout whose member layouts are laid out at the same starting offset. @@ -34,9 +33,8 @@ * @implSpec * Implementing classes are immutable, thread-safe and value-based. * - * @since 20 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface UnionLayout extends GroupLayout permits UnionLayoutImpl { /** diff --git a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java index 585fa9d467d..00f6541f133 100644 --- a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java @@ -25,12 +25,9 @@ package java.lang.foreign; -import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.nio.ByteOrder; - import jdk.internal.foreign.layout.ValueLayouts; -import jdk.internal.javac.PreviewFeature; /** * A layout that models values of basic data types. Examples of values modelled by a value layout are @@ -51,9 +48,8 @@ * @implSpec implementing classes and subclasses are immutable, thread-safe and value-based. * * @sealedGraph - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public sealed interface ValueLayout extends MemoryLayout permits ValueLayout.OfBoolean, ValueLayout.OfByte, ValueLayout.OfChar, ValueLayout.OfShort, ValueLayout.OfInt, ValueLayout.OfFloat, ValueLayout.OfLong, ValueLayout.OfDouble, AddressLayout { @@ -76,66 +72,6 @@ public sealed interface ValueLayout extends MemoryLayout permits @Override ValueLayout withoutName(); - /** - * Creates a strided var handle that can be used to access a memory segment as multi-dimensional - * array. This array has a notional sequence layout featuring {@code shape.length} nested sequence layouts. The element - * layout of the innermost sequence layout in the notional sequence layout is this value layout. The resulting var handle - * is obtained as if calling the {@link #varHandle(PathElement...)} method on the notional layout, with a layout - * path containing exactly {@code shape.length + 1} {@linkplain PathElement#sequenceElement() open sequence layout path elements}. - *

    - * For instance, the following method call: - * - * {@snippet lang=java : - * VarHandle arrayHandle = ValueLayout.JAVA_INT.arrayElementVarHandle(10, 20); - * } - * - * Is equivalent to the following code: - * - * {@snippet lang = java: - * SequenceLayout notionalLayout = MemoryLayout.sequenceLayout( - * MemoryLayout.sequenceLayout(10, MemoryLayout.sequenceLayout(20, ValueLayout.JAVA_INT))); - * VarHandle arrayHandle = notionalLayout.varHandle(PathElement.sequenceElement(), - * PathElement.sequenceElement(), - * PathElement.sequenceElement()); - *} - * - * The resulting var handle {@code arrayHandle} will feature 3 coordinates of type {@code long}; each coordinate - * is interpreted as an index into the corresponding sequence layout. If we refer to the var handle coordinates, from left - * to right, as {@code x}, {@code y} and {@code z} respectively, the final offset accessed by the var handle can be - * computed with the following formula: - * - *

    {@code
    -     * offset = (10 * 20 * 4 * x) + (20 * 4 * y) + (4 * z)
    -     * }
    - * - * Additionally, the values of {@code x}, {@code y} and {@code z} are constrained as follows: - *
      - *
    • {@code 0 <= x < notionalLayout.elementCount() }
    • - *
    • {@code 0 <= y < 10 }
    • - *
    • {@code 0 <= z < 20 }
    • - *
    - *

    - * Consider the following access expressions: - * {@snippet lang=java : - * int value1 = (int) arrayHandle.get(10, 2, 4); // ok, accessed offset = 8176 - * int value2 = (int) arrayHandle.get(0, 0, 30); // out of bounds value for z - * } - * In the first case, access is well-formed, as the values for {@code x}, {@code y} and {@code z} conform to - * the bounds specified above. In the second case, access fails with {@link IndexOutOfBoundsException}, - * as the value for {@code z} is outside its specified bounds. - * - * @param shape the size of each nested array dimension. - * @return a var handle which can be used to access a memory segment as a multi-dimensional array, - * featuring {@code shape.length + 1} - * {@code long} coordinates. - * @throws IllegalArgumentException if {@code shape[i] < 0}, for at least one index {@code i}. - * @throws UnsupportedOperationException if {@code byteAlignment() > byteSize()}. - * @see MethodHandles#memorySegmentViewVarHandle - * @see MemoryLayout#varHandle(PathElement...) - * @see SequenceLayout - */ - VarHandle arrayElementVarHandle(int... shape); - /** * {@return the carrier associated with this value layout} */ @@ -149,19 +85,40 @@ public sealed interface ValueLayout extends MemoryLayout permits /** * {@inheritDoc} + * * @throws IllegalArgumentException {@inheritDoc} */ @Override ValueLayout withByteAlignment(long byteAlignment); + /** + * {@return a var handle which can be used to access values described by this value layout, in a given memory segment.} + *

    + * The returned var handle's {@linkplain VarHandle#varType() var type} is the {@linkplain ValueLayout#carrier() carrier type} of + * this value layout, and the list of coordinate types is {@code (MemorySegment, long)}, where the memory segment coordinate + * corresponds to the memory segment to be accessed, and the {@code long} coordinate corresponds to the byte offset + * into the accessed memory segment at which the access occurs. + *

    + * The returned var handle checks that accesses are aligned according to this value layout's + * {@linkplain MemoryLayout#byteAlignment() alignment constraint}. + * + * @apiNote This method is similar, but more efficient, than calling {@code MemoryLayout#varHandle(PathElement...)} + * with an empty path element array, as it avoids the creation of the var args array. + * + * @apiNote The returned var handle features certain access mode + * restrictions common to all memory access var handles derived from memory layouts. + * + * @see MemoryLayout#varHandle(PathElement...) + */ + VarHandle varHandle(); + /** * A value layout whose carrier is {@code boolean.class}. * * @see #JAVA_BOOLEAN - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfBoolean extends ValueLayout permits ValueLayouts.OfBooleanImpl { + sealed interface OfBoolean extends ValueLayout permits ValueLayouts.OfBooleanImpl { /** * {@inheritDoc} @@ -194,10 +151,9 @@ sealed interface OfBoolean extends ValueLayout permits ValueLayouts.OfBooleanImp * A value layout whose carrier is {@code byte.class}. * * @see #JAVA_BYTE - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfByte extends ValueLayout permits ValueLayouts.OfByteImpl { + sealed interface OfByte extends ValueLayout permits ValueLayouts.OfByteImpl { /** * {@inheritDoc} @@ -231,10 +187,9 @@ sealed interface OfByte extends ValueLayout permits ValueLayouts.OfByteImpl { * * @see #JAVA_CHAR * @see #JAVA_CHAR_UNALIGNED - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfChar extends ValueLayout permits ValueLayouts.OfCharImpl { + sealed interface OfChar extends ValueLayout permits ValueLayouts.OfCharImpl { /** * {@inheritDoc} @@ -268,10 +223,9 @@ sealed interface OfChar extends ValueLayout permits ValueLayouts.OfCharImpl { * * @see #JAVA_SHORT * @see #JAVA_SHORT_UNALIGNED - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfShort extends ValueLayout permits ValueLayouts.OfShortImpl { + sealed interface OfShort extends ValueLayout permits ValueLayouts.OfShortImpl { /** * {@inheritDoc} @@ -305,10 +259,9 @@ sealed interface OfShort extends ValueLayout permits ValueLayouts.OfShortImpl { * * @see #JAVA_INT * @see #JAVA_INT_UNALIGNED - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfInt extends ValueLayout permits ValueLayouts.OfIntImpl { + sealed interface OfInt extends ValueLayout permits ValueLayouts.OfIntImpl { /** * {@inheritDoc} @@ -342,10 +295,9 @@ sealed interface OfInt extends ValueLayout permits ValueLayouts.OfIntImpl { * * @see #JAVA_FLOAT * @see #JAVA_FLOAT_UNALIGNED - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfFloat extends ValueLayout permits ValueLayouts.OfFloatImpl { + sealed interface OfFloat extends ValueLayout permits ValueLayouts.OfFloatImpl { /** * {@inheritDoc} @@ -378,10 +330,9 @@ sealed interface OfFloat extends ValueLayout permits ValueLayouts.OfFloatImpl { * * @see #JAVA_LONG * @see #JAVA_LONG_UNALIGNED - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfLong extends ValueLayout permits ValueLayouts.OfLongImpl { + sealed interface OfLong extends ValueLayout permits ValueLayouts.OfLongImpl { /** * {@inheritDoc} @@ -415,10 +366,9 @@ sealed interface OfLong extends ValueLayout permits ValueLayouts.OfLongImpl { * * @see #JAVA_DOUBLE * @see #JAVA_DOUBLE_UNALIGNED - * @since 19 + * @since 22 */ - @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN) - sealed interface OfDouble extends ValueLayout permits ValueLayouts.OfDoubleImpl { + sealed interface OfDouble extends ValueLayout permits ValueLayouts.OfDoubleImpl { /** * {@inheritDoc} diff --git a/src/java.base/share/classes/java/lang/foreign/package-info.java b/src/java.base/share/classes/java/lang/foreign/package-info.java index 8a3bc1c0c4e..5bb4c5c4206 100644 --- a/src/java.base/share/classes/java/lang/foreign/package-info.java +++ b/src/java.base/share/classes/java/lang/foreign/package-info.java @@ -93,7 +93,7 @@ * ); * * try (Arena arena = Arena.ofConfined()) { - * MemorySegment cString = arena.allocateUtf8String("Hello"); + * MemorySegment cString = arena.allocateFrom("Hello"); * long len = (long)strlen.invokeExact(cString); // 5 * } *} @@ -109,7 +109,7 @@ * into a foreign function call, according to the rules specified by the ABI of the underlying platform. * The {@link java.lang.foreign.Arena} class also provides many useful methods for * interacting with foreign code, such as - * {@linkplain java.lang.foreign.SegmentAllocator#allocateUtf8String(java.lang.String) converting} Java strings into + * {@linkplain java.lang.foreign.SegmentAllocator#allocateFrom(java.lang.String) converting} Java strings into * zero-terminated, UTF-8 strings, as demonstrated in the above example. * *

    Restricted methods

    @@ -147,9 +147,7 @@ * * @spec jni/index.html Java Native Interface Specification * - * @since 19 + * @since 22 */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) package java.lang.foreign; -import jdk.internal.javac.PreviewFeature; diff --git a/src/java.base/share/classes/java/lang/foreign/snippet-files/Snippets.java b/src/java.base/share/classes/java/lang/foreign/snippet-files/Snippets.java index dd99c2b4f8d..95b9cce7541 100644 --- a/src/java.base/share/classes/java/lang/foreign/snippet-files/Snippets.java +++ b/src/java.base/share/classes/java/lang/foreign/snippet-files/Snippets.java @@ -122,7 +122,7 @@ public static void main(String[] args) { // @start region="slicing-arena-main": try (Arena slicingArena = new SlicingArena(1000)) { for (int i = 0; i < 10; i++) { - MemorySegment s = slicingArena.allocateArray(JAVA_INT, 1, 2, 3, 4, 5); + MemorySegment s = slicingArena.allocateFrom(JAVA_INT, 1, 2, 3, 4, 5); // ... } } // all memory allocated is released here @@ -148,7 +148,7 @@ static class AddressLayoutSnippets { void withTargetLayout() { AddressLayout addressLayout = ADDRESS; AddressLayout unboundedLayout = addressLayout.withTargetLayout( - sequenceLayout(ValueLayout.JAVA_BYTE)); + sequenceLayout(Long.MAX_VALUE, ValueLayout.JAVA_BYTE)); } } @@ -168,7 +168,7 @@ void downcall() throws Throwable { ); try (Arena arena = Arena.ofConfined()) { - MemorySegment str = arena.allocateUtf8String("Hello"); + MemorySegment str = arena.allocateFrom("Hello"); long len = (long) strlen.invokeExact(str); // 5 } @@ -197,7 +197,7 @@ static int qsortCompare(MemorySegment elem1, MemorySegment elem2) { try (Arena arena = Arena.ofConfined()) { MemorySegment compareFunc = linker.upcallStub(comparHandle, comparDesc, arena); - MemorySegment array = arena.allocateArray(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7); + MemorySegment array = arena.allocateFrom(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7); qsort.invokeExact(array, 10L, 4L, compareFunc); int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] @@ -288,7 +288,7 @@ void variadicFunc() throws Throwable { ); try (Arena arena = Arena.ofConfined()) { - int res = (int) printf.invokeExact(arena.allocateUtf8String("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4" + int res = (int) printf.invokeExact(arena.allocateFrom("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4" } } @@ -313,7 +313,7 @@ void captureCallState() throws Throwable { try (Arena arena = Arena.ofConfined()) { MemorySegment capturedState = arena.allocate(capturedStateLayout); handle.invoke(capturedState); - int errno = (int) errnoHandle.get(capturedState); + int errno = (int) errnoHandle.get(capturedState, 0L); // use errno } } @@ -351,8 +351,8 @@ void header() throws Throwable { MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(), PathElement.groupElement("kind")); - long offset1 = (long) offsetHandle.invokeExact(1L); // 8 - long offset2 = (long) offsetHandle.invokeExact(2L); // 16 + long offset1 = (long) offsetHandle.invokeExact(0L, 1L); // 8 + long offset2 = (long) offsetHandle.invokeExact(0L, 2L); // 16 } void sliceHandle() { @@ -396,7 +396,7 @@ void header() throws NoSuchMethodException, IllegalAccessException { { MemorySegment segment = null; // ... - VarHandle intHandle = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT); + VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); MethodHandle multiplyExact = MethodHandles.lookup() .findStatic(Math.class, "multiplyExact", MethodType.methodType(long.class, long.class, long.class)); @@ -408,8 +408,13 @@ void header() throws NoSuchMethodException, IllegalAccessException { { MemorySegment segment = null; // ... - VarHandle intHandle = ValueLayout.JAVA_INT.arrayElementVarHandle(); - int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12 + MemoryLayout segmentLayout = MemoryLayout.structLayout( + ValueLayout.JAVA_INT.withName("size"), + MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT).withName("data") // array of 4 elements + ); + VarHandle intHandle = segmentLayout.varHandle(MemoryLayout.PathElement.groupElement("data"), + MemoryLayout.PathElement.sequenceElement()); + int value = (int) intHandle.get(segment, 0L, 3L); // get int element at offset 0 + offsetof(data) + 3 * 4 = 12 } { @@ -524,10 +529,8 @@ void fill() { MemorySegment segment = null; byte value = 42; - var byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE) - .varHandle(MemoryLayout.PathElement.sequenceElement()); for (long l = 0; l < segment.byteSize(); l++) { - byteHandle.set(segment.address(), l, value); + segment.set(JAVA_BYTE, l, value); } } @@ -570,7 +573,7 @@ void header() throws Throwable { ); try (Arena arena = Arena.ofConfined()) { - MemorySegment cString = arena.allocateUtf8String("Hello"); + MemorySegment cString = arena.allocateFrom("Hello"); long len = (long) strlen.invokeExact(cString); // 5 } @@ -654,17 +657,6 @@ static class UnionLayoutSnippets { static class ValueLayoutSnippets { - void arrayElementVarHandle() { - VarHandle arrayHandle = ValueLayout.JAVA_INT.arrayElementVarHandle(10, 20); - - SequenceLayout arrayLayout = MemoryLayout.sequenceLayout( - MemoryLayout.sequenceLayout(10, - MemoryLayout.sequenceLayout(20, ValueLayout.JAVA_INT))); - - int value1 = (int) arrayHandle.get(10, 2, 4); // ok, accessed offset = 8176 - int value2 = (int) arrayHandle.get(0, 0, 30); // out of bounds value for z - } - void statics() { ADDRESS.withByteAlignment(1); JAVA_CHAR.withByteAlignment(1); diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 49de59d7aa5..da18a994a01 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -26,8 +26,6 @@ package java.lang.invoke; import jdk.internal.access.SharedSecrets; -import jdk.internal.foreign.Utils; -import jdk.internal.javac.PreviewFeature; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.org.objectweb.asm.ClassReader; @@ -45,10 +43,6 @@ import sun.security.util.SecurityConstants; import java.lang.constant.ConstantDescs; -import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; import java.lang.invoke.LambdaForm.BasicType; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -7978,85 +7972,6 @@ private static MethodType tableSwitchChecks(MethodHandle defaultCase, MethodHand return expectedType; } - /** - * Creates a var handle object, which can be used to dereference a {@linkplain java.lang.foreign.MemorySegment memory segment} - * at a given byte offset, using the provided value layout. - * - *

    The provided layout specifies the {@linkplain ValueLayout#carrier() carrier type}, - * the {@linkplain ValueLayout#byteSize() byte size}, - * the {@linkplain ValueLayout#byteAlignment() byte alignment} and the {@linkplain ValueLayout#order() byte order} - * associated with the returned var handle. - * - *

    The list of coordinate types associated with the returned var handle is {@code (MemorySegment, long)}, - * where the {@code long} coordinate type corresponds to byte offset into the given memory segment coordinate. - * Thus, the returned var handle accesses bytes at an offset in a given memory segment, composing bytes to or from - * a value of the var handle type. Moreover, the access operation will honor the endianness and the - * alignment constraints expressed in the provided layout. - * - *

    As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows: - * {@snippet lang="java" : - * GroupLayout seq = java.lang.foreign.MemoryLayout.structLayout( - * MemoryLayout.paddingLayout(4), - * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value") - * ); - * } - * To access the member layout named {@code value}, we can construct a memory segment view var handle as follows: - * {@snippet lang="java" : - * VarHandle handle = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int - * handle = MethodHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int - * } - * - * @apiNote The resulting var handle features certain access mode restrictions, - * which are common to all memory segment view var handles. A memory segment view var handle is associated - * with an access size {@code S} and an alignment constraint {@code B} - * (both expressed in bytes). We say that a memory access operation is fully aligned if it occurs - * at a memory address {@code A} which is compatible with both alignment constraints {@code S} and {@code B}. - * If access is fully aligned then following access modes are supported and are - * guaranteed to support atomic access: - *

      - *
    • read write access modes for all {@code T}, with the exception of - * access modes {@code get} and {@code set} for {@code long} and - * {@code double} on 32-bit platforms. - *
    • atomic update access modes for {@code int}, {@code long}, - * {@code float}, {@code double} or {@link MemorySegment}. - * (Future major platform releases of the JDK may support additional - * types for certain currently unsupported access modes.) - *
    • numeric atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}. - * (Future major platform releases of the JDK may support additional - * numeric types for certain currently unsupported access modes.) - *
    • bitwise atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}. - * (Future major platform releases of the JDK may support additional - * numeric types for certain currently unsupported access modes.) - *
    - * - * If {@code T} is {@code float}, {@code double} or {@link MemorySegment} then atomic - * update access modes compare values using their bitwise representation - * (see {@link Float#floatToRawIntBits}, - * {@link Double#doubleToRawLongBits} and {@link MemorySegment#address()}, respectively). - *

    - * Alternatively, a memory access operation is partially aligned if it occurs at a memory address {@code A} - * which is only compatible with the alignment constraint {@code B}; in such cases, access for anything other than the - * {@code get} and {@code set} access modes will result in an {@code IllegalStateException}. If access is partially aligned, - * atomic access is only guaranteed with respect to the largest power of two that divides the GCD of {@code A} and {@code S}. - *

    - * In all other cases, we say that a memory access operation is misaligned; in such cases an - * {@code IllegalStateException} is thrown, irrespective of the access mode being used. - *

    - * Finally, if {@code T} is {@code MemorySegment} all write access modes throw {@link IllegalArgumentException} - * unless the value to be written is a {@linkplain MemorySegment#isNative() native} memory segment. - * - * @param layout the value layout for which a memory access handle is to be obtained. - * @return the new memory segment view var handle. - * @throws NullPointerException if {@code layout} is {@code null}. - * @see MemoryLayout#varHandle(MemoryLayout.PathElement...) - * @since 19 - */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) - public static VarHandle memorySegmentViewVarHandle(ValueLayout layout) { - Objects.requireNonNull(layout); - return Utils.makeSegmentViewVarHandle(layout); - } - /** * Adapts a target var handle by pre-processing incoming and outgoing values using a pair of filter functions. *

    @@ -8087,9 +8002,8 @@ public static VarHandle memorySegmentViewVarHandle(ValueLayout layout) { * other than {@code (A... , S) -> T} and {@code (A... , T) -> S}, respectively, where {@code T} is the type of the target var handle, * or if it's determined that either {@code filterFromTarget} or {@code filterToTarget} throws any checked exceptions. * @throws NullPointerException if any of the arguments is {@code null}. - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarget, MethodHandle filterFromTarget) { return VarHandles.filterValue(target, filterToTarget, filterFromTarget); } @@ -8123,9 +8037,8 @@ public static VarHandle filterValue(VarHandle target, MethodHandle filterToTarge * or if more filters are provided than the actual number of coordinate types available starting at {@code pos}, * or if it's determined that any of the filters throws any checked exceptions. * @throws NullPointerException if any of the arguments is {@code null} or {@code filters} contains {@code null}. - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public static VarHandle filterCoordinates(VarHandle target, int pos, MethodHandle... filters) { return VarHandles.filterCoordinates(target, pos, filters); } @@ -8155,9 +8068,8 @@ public static VarHandle filterCoordinates(VarHandle target, int pos, MethodHandl * other than {@code T1, T2 ... Tn }, where {@code T1, T2 ... Tn} are the coordinate types starting at position {@code pos} * of the target var handle. * @throws NullPointerException if any of the arguments is {@code null} or {@code values} contains {@code null}. - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public static VarHandle insertCoordinates(VarHandle target, int pos, Object... values) { return VarHandles.insertCoordinates(target, pos, values); } @@ -8198,9 +8110,8 @@ public static VarHandle insertCoordinates(VarHandle target, int pos, Object... v * a coordinate of {@code newCoordinates}, or if two corresponding coordinate types in * the target var handle and in {@code newCoordinates} are not identical. * @throws NullPointerException if any of the arguments is {@code null} or {@code newCoordinates} contains {@code null}. - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public static VarHandle permuteCoordinates(VarHandle target, List> newCoordinates, int... reorder) { return VarHandles.permuteCoordinates(target, newCoordinates, reorder); } @@ -8242,9 +8153,8 @@ public static VarHandle permuteCoordinates(VarHandle target, List> newC * if the resulting var handle's type would have too many coordinates, * or if it's determined that {@code filter} throws any checked exceptions. * @throws NullPointerException if any of the arguments is {@code null}. - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) { return VarHandles.collectCoordinates(target, pos, filter); } @@ -8268,9 +8178,8 @@ public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHand * before calling the target var handle * @throws IllegalArgumentException if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive. * @throws NullPointerException if any of the arguments is {@code null} or {@code valueTypes} contains {@code null}. - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public static VarHandle dropCoordinates(VarHandle target, int pos, Class... valueTypes) { return VarHandles.dropCoordinates(target, pos, valueTypes); } diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java b/src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java index 199eb7d6c11..ffc2af1ec51 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandleSegmentViewBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -56,4 +56,8 @@ abstract sealed class VarHandleSegmentViewBase extends VarHandle permits static IllegalArgumentException newIllegalArgumentExceptionForMisalignedAccess(long address) { return new IllegalArgumentException("Misaligned access at address: " + address); } + + static UnsupportedOperationException newUnsupportedAccessModeForAlignment(long alignment) { + return new UnsupportedOperationException("Unsupported access mode for alignment: " + alignment); + } } diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template index 303acbdaeae..aa1c232e5df 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleSegmentView.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -43,7 +43,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); - static final int VM_ALIGN = $BoxType$.BYTES - 1; + static final int NON_PLAIN_ACCESS_MIN_ALIGN_MASK = $BoxType$.BYTES - 1; static final VarForm FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, long.class); @@ -104,16 +104,15 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { } @ForceInline - static long offset(AbstractMemorySegmentImpl bb, long offset, long alignmentMask) { - long address = offsetNoVMAlignCheck(bb, offset, alignmentMask); - if ((address & VM_ALIGN) != 0) { - throw VarHandleSegmentViewBase.newIllegalArgumentExceptionForMisalignedAccess(address); + static long offsetNonPlain(AbstractMemorySegmentImpl bb, long offset, long alignmentMask) { + if ((alignmentMask & NON_PLAIN_ACCESS_MIN_ALIGN_MASK) != NON_PLAIN_ACCESS_MIN_ALIGN_MASK) { + throw VarHandleSegmentViewBase.newUnsupportedAccessModeForAlignment(alignmentMask + 1); } - return address; + return offsetPlain(bb, offset, alignmentMask); } @ForceInline - static long offsetNoVMAlignCheck(AbstractMemorySegmentImpl bb, long offset, long alignmentMask) { + static long offsetPlain(AbstractMemorySegmentImpl bb, long offset, long alignmentMask) { long base = bb.unsafeGetOffset(); long address = base + offset; long maxAlignMask = bb.maxAlignMask(); @@ -130,18 +129,18 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { #if[floatingPoint] $rawType$ rawValue = SCOPED_MEMORY_ACCESS.get$RawType$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNoVMAlignCheck(bb, base, handle.alignmentMask), + offsetPlain(bb, base, handle.alignmentMask), handle.be); return $Type$.$rawType$BitsTo$Type$(rawValue); #else[floatingPoint] #if[byte] return SCOPED_MEMORY_ACCESS.get$Type$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNoVMAlignCheck(bb, base, handle.alignmentMask)); + offsetPlain(bb, base, handle.alignmentMask)); #else[byte] return SCOPED_MEMORY_ACCESS.get$Type$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNoVMAlignCheck(bb, base, handle.alignmentMask), + offsetPlain(bb, base, handle.alignmentMask), handle.be); #end[byte] #end[floatingPoint] @@ -154,19 +153,19 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { #if[floatingPoint] SCOPED_MEMORY_ACCESS.put$RawType$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNoVMAlignCheck(bb, base, handle.alignmentMask), + offsetPlain(bb, base, handle.alignmentMask), $Type$.$type$ToRaw$RawType$Bits(value), handle.be); #else[floatingPoint] #if[byte] SCOPED_MEMORY_ACCESS.put$Type$(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNoVMAlignCheck(bb, base, handle.alignmentMask), + offsetPlain(bb, base, handle.alignmentMask), value); #else[byte] SCOPED_MEMORY_ACCESS.put$Type$Unaligned(bb.sessionImpl(), bb.unsafeGetBase(), - offsetNoVMAlignCheck(bb, base, handle.alignmentMask), + offsetPlain(bb, base, handle.alignmentMask), value, handle.be); #end[byte] @@ -180,7 +179,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask))); + offsetNonPlain(bb, base, handle.alignmentMask))); } @ForceInline @@ -189,7 +188,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); SCOPED_MEMORY_ACCESS.put$RawType$Volatile(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, value)); } @@ -200,7 +199,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask))); + offsetNonPlain(bb, base, handle.alignmentMask))); } @ForceInline @@ -209,7 +208,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); SCOPED_MEMORY_ACCESS.put$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, value)); } @@ -220,7 +219,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.get$RawType$Opaque(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask))); + offsetNonPlain(bb, base, handle.alignmentMask))); } @ForceInline @@ -229,7 +228,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); SCOPED_MEMORY_ACCESS.put$RawType$Opaque(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, value)); } #if[CAS] @@ -240,7 +239,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -251,7 +250,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value))); } @@ -262,7 +261,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value))); } @@ -273,7 +272,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value))); } @@ -283,7 +282,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -293,7 +292,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -303,7 +302,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -313,7 +312,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { AbstractMemorySegmentImpl bb = checkAddress(obb, base, handle.length, false); return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, expected), convEndian(handle.be, value)); } @@ -324,7 +323,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, value))); } @@ -335,7 +334,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, value))); } @@ -346,7 +345,7 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { return convEndian(handle.be, SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), convEndian(handle.be, value))); } #end[CAS] @@ -359,10 +358,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), delta); } else { - return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), delta); + return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), delta); } } @@ -373,10 +372,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), delta); } else { - return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), delta); + return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), delta); } } @@ -387,10 +386,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), delta); } else { - return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), delta); + return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), delta); } } @@ -415,10 +414,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -429,10 +428,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -443,10 +442,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -469,10 +468,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -483,10 +482,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -497,10 +496,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -524,10 +523,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -538,10 +537,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } @@ -552,10 +551,10 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase { if (handle.be == BE) { return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(bb.sessionImpl(), bb.unsafeGetBase(), - offset(bb, base, handle.alignmentMask), + offsetNonPlain(bb, base, handle.alignmentMask), value); } else { - return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value); + return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, handle.alignmentMask), value); } } diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java index bdc392c59a8..f785b2290cb 100644 --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java @@ -1088,9 +1088,8 @@ public abstract MappedByteBuffer map(MapMode mode, long position, long size) * @throws UnsupportedOperationException * If an unsupported map mode is specified. * - * @since 19 + * @since 22 */ - @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) public MemorySegment map(MapMode mode, long offset, long size, Arena arena) throws IOException { diff --git a/src/java.base/share/classes/java/util/jar/Attributes.java b/src/java.base/share/classes/java/util/jar/Attributes.java index 33363fd566c..149bf38f67c 100644 --- a/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/src/java.base/share/classes/java/util/jar/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, 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 @@ -715,9 +715,10 @@ private static void addName(Map names, Name name) { // small footprint cost, but is likely to be quickly paid for by // reducing allocation when reading and parsing typical manifests - // JDK internal attributes + // JDK specific attributes addName(names, new Name("Add-Exports")); addName(names, new Name("Add-Opens")); + addName(names, new Name("Enable-Native-Access")); // LauncherHelper attributes addName(names, new Name("Launcher-Agent-Class")); addName(names, new Name("JavaFX-Application-Class")); diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index 6ea7abf6b95..29c64f2a1b6 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -273,7 +273,7 @@ public interface JavaLangAccess { * Ensure that the given module has native access. If not, warn or * throw exception depending on the configuration. */ - void ensureNativeAccess(Module m, Class owner, String methodName); + void ensureNativeAccess(Module m, Class owner, String methodName, Class currentClass); /** * Returns the ServicesCatalog for the given Layer. diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index c2c3ef3da18..6e84f7f4b9e 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -264,7 +264,7 @@ public final Optional asOverlappingSlice(MemorySegment other) { final long thatEnd = thatStart + that.byteSize(); if (thisStart < thatEnd && thisEnd > thatStart) { //overlap occurs - long offsetToThat = this.segmentOffset(that); + long offsetToThat = that.address() - this.address(); long newOffset = offsetToThat >= 0 ? offsetToThat : 0; return Optional.of(asSlice(newOffset, Math.min(this.byteSize() - newOffset, that.byteSize() + offsetToThat))); } @@ -272,15 +272,6 @@ public final Optional asOverlappingSlice(MemorySegment other) { return Optional.empty(); } - @Override - public final long segmentOffset(MemorySegment other) { - AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other); - if (unsafeGetBase() == that.unsafeGetBase()) { - return that.unsafeGetOffset() - this.unsafeGetOffset(); - } - throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa)."); - } - @Override public void load() { throw notAMappedSegment(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/ArenaImpl.java b/src/java.base/share/classes/jdk/internal/foreign/ArenaImpl.java new file mode 100644 index 00000000000..9d1baecc8b9 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/ArenaImpl.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.internal.foreign; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySegment.Scope; +import java.util.Objects; + +public final class ArenaImpl implements Arena { + + private final MemorySessionImpl session; + private final boolean shouldReserveMemory; + ArenaImpl(MemorySessionImpl session) { + this.session = session; + shouldReserveMemory = session instanceof ImplicitSession; + } + + @Override + public Scope scope() { + return session; + } + + @Override + public void close() { + session.close(); + } + + public MemorySegment allocateNoInit(long byteSize, long byteAlignment) { + Utils.checkAllocationSizeAndAlign(byteSize, byteAlignment); + return NativeMemorySegmentImpl.makeNativeSegmentNoZeroing(byteSize, byteAlignment, session, shouldReserveMemory); + } + + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + MemorySegment segment = allocateNoInit(byteSize, byteAlignment); + return segment.fill((byte)0); + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java index f368a8b7f23..f52c5e2ee64 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java @@ -39,8 +39,10 @@ import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.function.UnaryOperator; +import java.util.stream.IntStream; /** * This class provide support for constructing layout paths; that is, starting from a root path (see {@link #rootPath(MemoryLayout)}, @@ -61,6 +63,7 @@ public class LayoutPath { private static final MethodHandle MH_SLICE_LAYOUT; private static final MethodHandle MH_CHECK_ALIGN; private static final MethodHandle MH_SEGMENT_RESIZE; + private static final MethodHandle MH_ADD; static { try { @@ -72,9 +75,11 @@ public class LayoutPath { MH_SLICE_LAYOUT = lookup.findVirtual(MemorySegment.class, "asSlice", MethodType.methodType(MemorySegment.class, long.class, MemoryLayout.class)); MH_CHECK_ALIGN = lookup.findStatic(LayoutPath.class, "checkAlign", - MethodType.methodType(MemorySegment.class, MemorySegment.class, MemoryLayout.class)); + MethodType.methodType(void.class, MemorySegment.class, long.class, MemoryLayout.class)); MH_SEGMENT_RESIZE = lookup.findStatic(LayoutPath.class, "resizeSegment", MethodType.methodType(MemorySegment.class, MemorySegment.class, MemoryLayout.class)); + MH_ADD = lookup.findStatic(Long.class, "sum", + MethodType.methodType(long.class, long.class, long.class)); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } @@ -202,20 +207,34 @@ public VarHandle dereferenceHandle(boolean adapt) { // If we have an enclosing layout, drop the alignment check for the accessed element, // we check the root layout instead ValueLayout accessedLayout = enclosing != null ? valueLayout.withByteAlignment(1) : valueLayout; - VarHandle handle = Utils.makeSegmentViewVarHandle(accessedLayout); + VarHandle handle = accessedLayout.varHandle(); handle = MethodHandles.collectCoordinates(handle, 1, offsetHandle()); // we only have to check the alignment of the root layout for the first dereference we do, // as each dereference checks the alignment of the target address when constructing its segment // (see Utils::longToAddress) if (derefAdapters.length == 0 && enclosing != null) { - MethodHandle checkHandle = MethodHandles.insertArguments(MH_CHECK_ALIGN, 1, rootLayout()); - handle = MethodHandles.filterCoordinates(handle, 0, checkHandle); + // insert align check for the root layout on the initial MS + offset + List> coordinateTypes = handle.coordinateTypes(); + MethodHandle alignCheck = MethodHandles.insertArguments(MH_CHECK_ALIGN, 2, rootLayout()); + handle = MethodHandles.collectCoordinates(handle, 0, alignCheck); + int[] reorder = IntStream.concat(IntStream.of(0, 1), IntStream.range(0, coordinateTypes.size())).toArray(); + handle = MethodHandles.permuteCoordinates(handle, coordinateTypes, reorder); } if (adapt) { + if (derefAdapters.length > 0) { + // plug up the base offset if we have at least 1 enclosing dereference + handle = MethodHandles.insertCoordinates(handle, 1, 0); + } for (int i = derefAdapters.length; i > 0; i--) { - handle = MethodHandles.collectCoordinates(handle, 0, derefAdapters[i - 1]); + MethodHandle adapter = derefAdapters[i - 1]; + // the first/outermost adapter will have a base offset coordinate, the rest are constant 0 + if (i > 1) { + // plug in a constant 0 base offset for all but the outermost access in a deref chain + adapter = MethodHandles.insertArguments(adapter, 1, 0); + } + handle = MethodHandles.collectCoordinates(handle, 0, adapter); } } return handle; @@ -228,14 +247,14 @@ private static long addScaledOffset(long base, long index, long stride, long bou } public MethodHandle offsetHandle() { - MethodHandle mh = MethodHandles.identity(long.class); - for (int i = strides.length - 1; i >=0; i--) { + MethodHandle mh = MethodHandles.insertArguments(MH_ADD, 0, offset); + for (int i = strides.length - 1; i >= 0; i--) { MethodHandle collector = MethodHandles.insertArguments(MH_ADD_SCALED_OFFSET, 2, strides[i], bounds[i]); // (J, ...) -> J to (J, J, ...) -> J // i.e. new coord is prefixed. Last coord will correspond to innermost layout mh = MethodHandles.collectArguments(mh, 0, collector); } - mh = MethodHandles.insertArguments(mh, 0, offset); + return mh; } @@ -253,21 +272,24 @@ public MethodHandle sliceHandle() { sliceHandle = MH_SLICE_LAYOUT; // (MS, long, MemoryLayout) -> MS sliceHandle = MethodHandles.insertArguments(sliceHandle, 2, layout); // (MS, long) -> MS } - sliceHandle = MethodHandles.collectArguments(sliceHandle, 1, offsetHandle()); // (MS, ...) -> MS + sliceHandle = MethodHandles.collectArguments(sliceHandle, 1, offsetHandle()); // (MS, long, ...) -> MS if (enclosing != null) { - MethodHandle checkHandle = MethodHandles.insertArguments(MH_CHECK_ALIGN, 1, rootLayout()); - sliceHandle = MethodHandles.filterArguments(sliceHandle, 0, checkHandle); + // insert align check for the root layout on the initial MS + offset + MethodType oldType = sliceHandle.type(); + MethodHandle alignCheck = MethodHandles.insertArguments(MH_CHECK_ALIGN, 2, rootLayout()); + sliceHandle = MethodHandles.collectArguments(sliceHandle, 0, alignCheck); // (MS, long, MS, long) -> MS + int[] reorder = IntStream.concat(IntStream.of(0, 1), IntStream.range(0, oldType.parameterCount())).toArray(); + sliceHandle = MethodHandles.permuteArguments(sliceHandle, oldType, reorder); // (MS, long, ...) -> MS } return sliceHandle; } - private static MemorySegment checkAlign(MemorySegment segment, MemoryLayout constraint) { - if (!((AbstractMemorySegmentImpl) segment).isAlignedForElement(0, constraint)) { + private static void checkAlign(MemorySegment segment, long offset, MemoryLayout constraint) { + if (!((AbstractMemorySegmentImpl) segment).isAlignedForElement(offset, constraint)) { throw new IllegalArgumentException("Target offset incompatible with alignment constraints: " + constraint.byteAlignment()); } - return segment; } public MemoryLayout layout() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java index 1d145c09351..c8c7dd2e543 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java @@ -77,17 +77,7 @@ public abstract sealed class MemorySessionImpl } public Arena asArena() { - return new Arena() { - @Override - public Scope scope() { - return MemorySessionImpl.this; - } - - @Override - public void close() { - MemorySessionImpl.this.close(); - } - }; + return new ArenaImpl(this); } @ForceInline @@ -153,11 +143,6 @@ public static MemorySessionImpl createImplicit(Cleaner cleaner) { return new ImplicitSession(cleaner); } - public MemorySegment allocate(long byteSize, long byteAlignment) { - Utils.checkAllocationSizeAndAlign(byteSize, byteAlignment); - return NativeMemorySegmentImpl.makeNativeSegment(byteSize, byteAlignment, this); - } - public abstract void release0(); public abstract void acquire0(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java index 28d038e39b3..6575388b025 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java @@ -33,7 +33,6 @@ import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.vm.annotation.ForceInline; -import sun.security.action.GetBooleanAction; /** * Implementation for native memory segments. A native memory segment is essentially a wrapper around @@ -46,7 +45,6 @@ public sealed class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl pe // The maximum alignment supported by malloc - typically 16 bytes on // 64-bit platforms and 8 bytes on 32-bit platforms. private static final long MAX_MALLOC_ALIGN = Unsafe.ADDRESS_SIZE == 4 ? 8 : 16; - private static final boolean SKIP_ZERO_MEMORY = GetBooleanAction.privilegedGetProperty("jdk.internal.foreign.skipZeroMemory"); final long min; @@ -115,7 +113,8 @@ public long maxAlignMask() { // factories - public static MemorySegment makeNativeSegment(long byteSize, long byteAlignment, MemorySessionImpl sessionImpl) { + public static MemorySegment makeNativeSegmentNoZeroing(long byteSize, long byteAlignment, MemorySessionImpl sessionImpl, + boolean shouldReserve) { sessionImpl.checkValidState(); if (VM.isDirectMemoryPageAligned()) { byteAlignment = Math.max(byteAlignment, NIO_ACCESS.pageSize()); @@ -124,12 +123,11 @@ public static MemorySegment makeNativeSegment(long byteSize, long byteAlignment, byteSize + (byteAlignment - 1) : byteSize); - NIO_ACCESS.reserveMemory(alignedSize, byteSize); - - long buf = UNSAFE.allocateMemory(alignedSize); - if (!SKIP_ZERO_MEMORY) { - UNSAFE.setMemory(buf, alignedSize, (byte)0); + if (shouldReserve) { + NIO_ACCESS.reserveMemory(alignedSize, byteSize); } + + long buf = allocateMemoryWrapper(alignedSize); long alignedBuf = Utils.alignUp(buf, byteAlignment); AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(buf, alignedSize, false, sessionImpl); @@ -137,7 +135,9 @@ public static MemorySegment makeNativeSegment(long byteSize, long byteAlignment, @Override public void cleanup() { UNSAFE.freeMemory(buf); - NIO_ACCESS.unreserveMemory(alignedSize, byteSize); + if (shouldReserve) { + NIO_ACCESS.unreserveMemory(alignedSize, byteSize); + } } }); if (alignedSize != byteSize) { @@ -147,6 +147,14 @@ public void cleanup() { return segment; } + private static long allocateMemoryWrapper(long size) { + try { + return UNSAFE.allocateMemory(size); + } catch (IllegalArgumentException ex) { + throw new OutOfMemoryError(); + } + } + // Unsafe native segment factories. These are used by the implementation code, to skip the sanity checks // associated with MemorySegment::ofAddress. diff --git a/src/java.base/share/classes/jdk/internal/foreign/SlicingAllocator.java b/src/java.base/share/classes/jdk/internal/foreign/SlicingAllocator.java index 36f8551f448..db7d476053e 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SlicingAllocator.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SlicingAllocator.java @@ -31,13 +31,11 @@ public final class SlicingAllocator implements SegmentAllocator { private final MemorySegment segment; - private final long maxAlign; private long sp = 0L; public SlicingAllocator(MemorySegment segment) { this.segment = segment; - this.maxAlign = ((AbstractMemorySegmentImpl)segment).maxAlignMask(); } MemorySegment trySlice(long byteSize, long byteAlignment) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/StringSupport.java b/src/java.base/share/classes/jdk/internal/foreign/StringSupport.java new file mode 100644 index 00000000000..4571a7c55c5 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/StringSupport.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.internal.foreign; + +import java.lang.foreign.MemorySegment; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static java.lang.foreign.ValueLayout.JAVA_SHORT; +import static java.lang.foreign.ValueLayout.JAVA_INT; + +/** + * Miscellaneous functions to read and write strings, in various charsets. + */ +public class StringSupport { + public static String read(MemorySegment segment, long offset, Charset charset) { + return switch (CharsetKind.of(charset)) { + case SINGLE_BYTE -> readFast_byte(segment, offset, charset); + case DOUBLE_BYTE -> readFast_short(segment, offset, charset); + case QUAD_BYTE -> readFast_int(segment, offset, charset); + }; + } + + public static void write(MemorySegment segment, long offset, Charset charset, String string) { + switch (CharsetKind.of(charset)) { + case SINGLE_BYTE -> writeFast_byte(segment, offset, charset, string); + case DOUBLE_BYTE -> writeFast_short(segment, offset, charset, string); + case QUAD_BYTE -> writeFast_int(segment, offset, charset, string); + } + } + private static String readFast_byte(MemorySegment segment, long offset, Charset charset) { + long len = strlen_byte(segment, offset); + byte[] bytes = new byte[(int)len]; + MemorySegment.copy(segment, JAVA_BYTE, offset, bytes, 0, (int)len); + return new String(bytes, charset); + } + + private static void writeFast_byte(MemorySegment segment, long offset, Charset charset, String string) { + byte[] bytes = string.getBytes(charset); + MemorySegment.copy(bytes, 0, segment, JAVA_BYTE, offset, bytes.length); + segment.set(JAVA_BYTE, offset + bytes.length, (byte)0); + } + + private static String readFast_short(MemorySegment segment, long offset, Charset charset) { + long len = strlen_short(segment, offset); + byte[] bytes = new byte[(int)len]; + MemorySegment.copy(segment, JAVA_BYTE, offset, bytes, 0, (int)len); + return new String(bytes, charset); + } + + private static void writeFast_short(MemorySegment segment, long offset, Charset charset, String string) { + byte[] bytes = string.getBytes(charset); + MemorySegment.copy(bytes, 0, segment, JAVA_BYTE, offset, bytes.length); + segment.set(JAVA_SHORT, offset + bytes.length, (short)0); + } + + private static String readFast_int(MemorySegment segment, long offset, Charset charset) { + long len = strlen_int(segment, offset); + byte[] bytes = new byte[(int)len]; + MemorySegment.copy(segment, JAVA_BYTE, offset, bytes, 0, (int)len); + return new String(bytes, charset); + } + + private static void writeFast_int(MemorySegment segment, long offset, Charset charset, String string) { + byte[] bytes = string.getBytes(charset); + MemorySegment.copy(bytes, 0, segment, JAVA_BYTE, offset, bytes.length); + segment.set(JAVA_INT, offset + bytes.length, 0); + } + + private static int strlen_byte(MemorySegment segment, long start) { + // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int) + for (int offset = 0; offset >= 0; offset++) { + byte curr = segment.get(JAVA_BYTE, start + offset); + if (curr == 0) { + return offset; + } + } + throw new IllegalArgumentException("String too large"); + } + + private static int strlen_short(MemorySegment segment, long start) { + // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int) + for (int offset = 0; offset >= 0; offset += 2) { + short curr = segment.get(JAVA_SHORT, start + offset); + if (curr == 0) { + return offset; + } + } + throw new IllegalArgumentException("String too large"); + } + + private static int strlen_int(MemorySegment segment, long start) { + // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int) + for (int offset = 0; offset >= 0; offset += 4) { + int curr = segment.get(JAVA_INT, start + offset); + if (curr == 0) { + return offset; + } + } + throw new IllegalArgumentException("String too large"); + } + + public enum CharsetKind { + SINGLE_BYTE(1), + DOUBLE_BYTE(2), + QUAD_BYTE(4); + + final int terminatorCharSize; + + CharsetKind(int terminatorCharSize) { + this.terminatorCharSize = terminatorCharSize; + } + + public int terminatorCharSize() { + return terminatorCharSize; + } + + public static CharsetKind of(Charset charset) { + if (charset == StandardCharsets.UTF_8 || charset == StandardCharsets.ISO_8859_1 || charset == StandardCharsets.US_ASCII) { + return CharsetKind.SINGLE_BYTE; + } else if (charset == StandardCharsets.UTF_16LE || charset == StandardCharsets.UTF_16BE || charset == StandardCharsets.UTF_16) { + return CharsetKind.DOUBLE_BYTE; + } else if (charset == StandardCharsets.UTF_32LE || charset == StandardCharsets.UTF_32BE || charset == StandardCharsets.UTF_32) { + return CharsetKind.QUAD_BYTE; + } else { + throw new IllegalArgumentException("Unsupported charset: " + charset); + } + } + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/Utils.java b/src/java.base/share/classes/jdk/internal/foreign/Utils.java index 3e8f012891e..7cbb07d0c10 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Utils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/Utils.java @@ -29,7 +29,6 @@ import java.lang.foreign.AddressLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.SegmentAllocator; import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; @@ -47,7 +46,6 @@ import jdk.internal.vm.annotation.ForceInline; import sun.invoke.util.Wrapper; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static sun.security.action.GetPropertyAction.privilegedGetProperty; /** @@ -98,7 +96,19 @@ static VarHandle put(ValueLayout layout, VarHandle handle) { VarHandle prev = HANDLE_MAP.putIfAbsent(layout, handle); return prev != null ? prev : handle; } + + static VarHandle get(ValueLayout layout) { + return HANDLE_MAP.get(layout); + } } + layout = layout.withoutName(); // name doesn't matter + // keep the addressee layout as it's used below + + VarHandle handle = VarHandleCache.get(layout); + if (handle != null) { + return handle; + } + Class baseCarrier = layout.carrier(); if (layout.carrier() == MemorySegment.class) { baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) { @@ -110,7 +120,7 @@ static VarHandle put(ValueLayout layout, VarHandle handle) { baseCarrier = byte.class; } - VarHandle handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier, + handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier, layout.byteAlignment() - 1, layout.order()); if (layout.carrier() == boolean.class) { @@ -149,18 +159,6 @@ public static MemorySegment longToAddress(long addr, long size, long align, Memo return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, size, scope); } - public static void copy(MemorySegment addr, byte[] bytes) { - var heapSegment = MemorySegment.ofArray(bytes); - addr.copyFrom(heapSegment); - addr.set(JAVA_BYTE, bytes.length, (byte)0); - } - - public static MemorySegment toCString(byte[] bytes, SegmentAllocator allocator) { - MemorySegment addr = allocator.allocate(bytes.length + 1); - copy(addr, bytes); - return addr; - } - @ForceInline public static boolean isAligned(long offset, long align) { return (offset & (align - 1)) == 0; diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java index e0c5c5575fc..ae41d4f1756 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java @@ -54,6 +54,7 @@ import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import java.util.HashSet; import java.util.List; import java.nio.ByteOrder; import java.util.Objects; @@ -73,6 +74,7 @@ public interface UpcallStubFactory { private record LinkRequest(FunctionDescriptor descriptor, LinkerOptions options) {} private final SoftReferenceCache DOWNCALL_CACHE = new SoftReferenceCache<>(); private final SoftReferenceCache UPCALL_CACHE = new SoftReferenceCache<>(); + private final Set CANONICAL_LAYOUTS_CACHE = new HashSet<>(canonicalLayouts().values()); @Override @CallerSensitive @@ -213,7 +215,7 @@ private void checkLayoutRecursive(MemoryLayout layout) { } // check for trailing padding - private static void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) { + private void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) { long expectedSize = Utils.alignUp(maxUnpaddedOffset, gl.byteAlignment()); if (gl.byteSize() != expectedSize) { throw new IllegalArgumentException("Layout '" + gl + "' has unexpected size: " @@ -223,7 +225,7 @@ private static void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) { // checks both that there is no excess padding between 'memberLayout' and // the previous layout - private static void checkMemberOffset(StructLayout parent, MemoryLayout memberLayout, + private void checkMemberOffset(StructLayout parent, MemoryLayout memberLayout, long lastUnpaddedOffset, long offset) { long expectedOffset = Utils.alignUp(lastUnpaddedOffset, memberLayout.byteAlignment()); if (expectedOffset != offset) { @@ -232,17 +234,17 @@ private static void checkMemberOffset(StructLayout parent, MemoryLayout memberLa } } - private static void checkSupported(ValueLayout valueLayout) { + private void checkSupported(ValueLayout valueLayout) { valueLayout = valueLayout.withoutName(); if (valueLayout instanceof AddressLayout addressLayout) { valueLayout = addressLayout.withoutTargetLayout(); } - if (!SUPPORTED_LAYOUTS.contains(valueLayout.withoutName())) { + if (!CANONICAL_LAYOUTS_CACHE.contains(valueLayout.withoutName())) { throw new IllegalArgumentException("Unsupported layout: " + valueLayout); } } - private static void checkHasNaturalAlignment(MemoryLayout layout) { + private void checkHasNaturalAlignment(MemoryLayout layout) { if (!((AbstractLayout) layout).hasNaturalAlignment()) { throw new IllegalArgumentException("Layout alignment must be natural alignment: " + layout); } @@ -273,16 +275,4 @@ private static FunctionDescriptor stripNames(FunctionDescriptor function) { .map(rl -> FunctionDescriptor.of(stripNames(rl), stripNames(function.argumentLayouts()))) .orElseGet(() -> FunctionDescriptor.ofVoid(stripNames(function.argumentLayouts()))); } - - private static final Set SUPPORTED_LAYOUTS = Set.of( - ValueLayout.JAVA_BOOLEAN, - ValueLayout.JAVA_BYTE, - ValueLayout.JAVA_CHAR, - ValueLayout.JAVA_SHORT, - ValueLayout.JAVA_INT, - ValueLayout.JAVA_FLOAT, - ValueLayout.JAVA_LONG, - ValueLayout.JAVA_DOUBLE, - ValueLayout.ADDRESS - ); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingInterpreter.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingInterpreter.java index bc0e2b0c5d6..71fcd3b7b25 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingInterpreter.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingInterpreter.java @@ -49,12 +49,12 @@ static Object box(List bindings, LoadFunc loadFunc, SegmentAllocator al } @FunctionalInterface - interface StoreFunc { + public interface StoreFunc { void store(VMStorage storage, Class type, Object o); } @FunctionalInterface - interface LoadFunc { + public interface LoadFunc { Object load(VMStorage storage, Class type); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java index fe1ac10b518..e301f692167 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java @@ -192,7 +192,7 @@ public int capturedStateMask() { } public boolean needsTransition() { - return !linkerOptions.isTrivial(); + return !linkerOptions.isCritical(); } public int numLeadingParams() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java b/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java index 2c2bcbcc163..3729093f09e 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java @@ -63,7 +63,11 @@ private static LinkerOptions forShared(BiConsumer= 0; offset++) { - byte curr = segment.get(JAVA_BYTE, start + offset); - if (curr == 0) { - return offset; - } - } - throw new IllegalArgumentException("String too large"); - } - static Map indexMap(Binding.Move[] moves) { return IntStream.range(0, moves.length) .boxed() @@ -434,20 +416,6 @@ public MemorySegment allocate(long byteSize, long byteAlignment) { }; } - public static final class SimpleVaArg { - public final MemoryLayout layout; - public final Object value; - - public SimpleVaArg(MemoryLayout layout, Object value) { - this.layout = layout; - this.value = value; - } - - public VarHandle varHandle() { - return layout.varHandle(); - } - } - static void writeOverSized(MemorySegment ptr, Class type, Object o) { // use VH_LONG for integers to zero out the whole register in the process if (type == long.class) { @@ -515,4 +483,35 @@ static Object read(MemorySegment ptr, long offset, Class type) { throw new IllegalArgumentException("Unsupported carrier: " + type); } } + + public static Map canonicalLayouts(ValueLayout longLayout, ValueLayout sizetLayout, ValueLayout wchartLayout) { + return Map.ofEntries( + // specified canonical layouts + Map.entry("bool", ValueLayout.JAVA_BOOLEAN), + Map.entry("char", ValueLayout.JAVA_BYTE), + Map.entry("short", ValueLayout.JAVA_SHORT), + Map.entry("int", ValueLayout.JAVA_INT), + Map.entry("float", ValueLayout.JAVA_FLOAT), + Map.entry("long", longLayout), + Map.entry("long long", ValueLayout.JAVA_LONG), + Map.entry("double", ValueLayout.JAVA_DOUBLE), + Map.entry("void*", ValueLayout.ADDRESS), + Map.entry("size_t", sizetLayout), + Map.entry("wchar_t", wchartLayout), + // unspecified size-dependent layouts + Map.entry("int8_t", ValueLayout.JAVA_BYTE), + Map.entry("int16_t", ValueLayout.JAVA_SHORT), + Map.entry("int32_t", ValueLayout.JAVA_INT), + Map.entry("int64_t", ValueLayout.JAVA_LONG), + // unspecified JNI layouts + Map.entry("jboolean", ValueLayout.JAVA_BOOLEAN), + Map.entry("jchar", ValueLayout.JAVA_CHAR), + Map.entry("jbyte", ValueLayout.JAVA_BYTE), + Map.entry("jshort", ValueLayout.JAVA_SHORT), + Map.entry("jint", ValueLayout.JAVA_INT), + Map.entry("jlong", ValueLayout.JAVA_LONG), + Map.entry("jfloat", ValueLayout.JAVA_FLOAT), + Map.entry("jdouble", ValueLayout.JAVA_DOUBLE) + ); + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java index 28ff423d388..54307e1ec21 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java @@ -27,12 +27,16 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.aarch64.CallArranger; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; /** * ABI implementation based on ARM document "Procedure Call Standard for @@ -40,6 +44,9 @@ */ public final class LinuxAArch64Linker extends AbstractLinker { + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); + public static LinuxAArch64Linker getInstance() { final class Holder { private static final LinuxAArch64Linker INSTANCE = new LinuxAArch64Linker(); @@ -66,4 +73,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.LITTLE_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java index 1a1bdc31be9..3f380a04db8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java @@ -27,12 +27,16 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.aarch64.CallArranger; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; /** * ABI implementation for macOS on Apple silicon. Based on AAPCS with @@ -40,6 +44,9 @@ */ public final class MacOsAArch64Linker extends AbstractLinker { + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); + public static MacOsAArch64Linker getInstance() { final class Holder { private static final MacOsAArch64Linker INSTANCE = new MacOsAArch64Linker(); @@ -66,4 +73,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.LITTLE_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java index a654d23fc89..71d18d7b182 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java @@ -28,18 +28,25 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.aarch64.CallArranger; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; /** * ABI implementation for Windows/AArch64. Based on AAPCS with * changes to va_list. */ public final class WindowsAArch64Linker extends AbstractLinker { + + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.JAVA_CHAR); private static WindowsAArch64Linker instance; public static WindowsAArch64Linker getInstance() { @@ -63,4 +70,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.LITTLE_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java index 465a17d2298..f5e3c29fc81 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FFIType.java @@ -37,13 +37,13 @@ import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Predicate; import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_INT; import static java.lang.foreign.ValueLayout.JAVA_LONG; import static java.lang.foreign.ValueLayout.JAVA_SHORT; @@ -58,18 +58,14 @@ * } ffi_type; */ class FFIType { - private static final ValueLayout SIZE_T = switch ((int) ADDRESS.byteSize()) { - case 8 -> JAVA_LONG; - case 4 -> JAVA_INT; - default -> throw new IllegalStateException("Address size not supported: " + ADDRESS.byteSize()); - }; + static final ValueLayout SIZE_T = layoutFor((int)ADDRESS.byteSize()); private static final ValueLayout UNSIGNED_SHORT = JAVA_SHORT; private static final StructLayout LAYOUT = Utils.computePaddedStructLayout( SIZE_T, UNSIGNED_SHORT, UNSIGNED_SHORT.withName("type"), ADDRESS.withName("elements")); private static final VarHandle VH_TYPE = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("type")); private static final VarHandle VH_ELEMENTS = LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("elements")); - private static final VarHandle VH_SIZE_T_ARRAY = SIZE_T.arrayElementVarHandle(); + private static final VarHandle VH_SIZE_T = SIZE_T.varHandle(); private static MemorySegment make(List elements, FFIABI abi, Arena scope) { MemorySegment elementsSeg = scope.allocate((elements.size() + 1) * ADDRESS.byteSize()); @@ -83,8 +79,8 @@ private static MemorySegment make(List elements, FFIABI abi, Arena elementsSeg.setAtIndex(ADDRESS, i, MemorySegment.NULL); MemorySegment ffiType = scope.allocate(LAYOUT); - VH_TYPE.set(ffiType, LibFallback.structTag()); - VH_ELEMENTS.set(ffiType, elementsSeg); + VH_TYPE.set(ffiType, 0L, LibFallback.structTag()); + VH_ELEMENTS.set(ffiType, 0L, elementsSeg); return ffiType; } @@ -132,7 +128,7 @@ private static void verifyStructType(StructLayout structLayout, List") @@ -143,4 +139,23 @@ private static void verifyStructType(StructLayout structLayout, List JAVA_BYTE; + case 2 -> JAVA_SHORT; + case 4 -> JAVA_INT; + case 8 -> JAVA_LONG; + default -> throw new IllegalStateException("Unsupported size: " + byteSize); + }; + } + + private static long sizeTAtIndex(MemorySegment segment, int index) { + long offset = SIZE_T.scale(0, index); + if (VH_SIZE_T.varType() == long.class) { + return (long) VH_SIZE_T.get(segment, offset); + } else { + return (int) VH_SIZE_T.get(segment, offset); // 'erase' to long + } + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java index 1adb6a6da9d..8e688c06eac 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java @@ -46,9 +46,18 @@ import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.function.Consumer; import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static java.lang.foreign.ValueLayout.JAVA_CHAR; +import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; +import static java.lang.foreign.ValueLayout.JAVA_FLOAT; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static java.lang.foreign.ValueLayout.JAVA_SHORT; import static java.lang.invoke.MethodHandles.foldArguments; public final class FallbackLinker extends AbstractLinker { @@ -283,4 +292,47 @@ private static Object readValue(MemorySegment seg, MemoryLayout layout) { assert layout == null; return null; } + + @Override + public Map canonicalLayouts() { + // Avoid eager dependency on LibFallback, so we can safely check LibFallback.SUPPORTED + class Holder { + static final Map CANONICAL_LAYOUTS; + + static { + int wchar_size = LibFallback.wcharSize(); + MemoryLayout wchartLayout = switch(wchar_size) { + case 2 -> JAVA_CHAR; // prefer JAVA_CHAR + default -> FFIType.layoutFor(wchar_size); + }; + + CANONICAL_LAYOUTS = Map.ofEntries( + // specified canonical layouts + Map.entry("bool", JAVA_BOOLEAN), + Map.entry("char", JAVA_BYTE), + Map.entry("float", JAVA_FLOAT), + Map.entry("long long", JAVA_LONG), + Map.entry("double", JAVA_DOUBLE), + Map.entry("void*", ADDRESS), + // platform-dependent sizes + Map.entry("size_t", FFIType.SIZE_T), + Map.entry("short", FFIType.layoutFor(LibFallback.shortSize())), + Map.entry("int", FFIType.layoutFor(LibFallback.intSize())), + Map.entry("long", FFIType.layoutFor(LibFallback.longSize())), + Map.entry("wchar_t", wchartLayout), + // JNI types + Map.entry("jboolean", JAVA_BOOLEAN), + Map.entry("jchar", JAVA_CHAR), + Map.entry("jbyte", JAVA_BYTE), + Map.entry("jshort", JAVA_SHORT), + Map.entry("jint", JAVA_INT), + Map.entry("jlong", JAVA_LONG), + Map.entry("jfloat", JAVA_FLOAT), + Map.entry("jdouble", JAVA_DOUBLE) + ); + } + } + + return Holder.CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/LibFallback.java b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/LibFallback.java index f4461fc2f4f..7318c71b82f 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/LibFallback.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/fallback/LibFallback.java @@ -65,6 +65,12 @@ public Boolean run() { static MemorySegment pointerType() { return NativeConstants.POINTER_TYPE; } static MemorySegment voidType() { return NativeConstants.VOID_TYPE; } + // platform-dependent types + static int shortSize() { return NativeConstants.SIZEOF_SHORT; } + static int intSize() { return NativeConstants.SIZEOF_INT; } + static int longSize() {return NativeConstants.SIZEOF_LONG; } + static int wcharSize() {return NativeConstants.SIZEOF_WCHAR; } + static short structTag() { return NativeConstants.STRUCT_TAG; } private static final MethodType UPCALL_TARGET_TYPE = MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class); @@ -222,6 +228,10 @@ private static void checkStatus(int code) { private static native long ffi_type_float(); private static native long ffi_type_double(); private static native long ffi_type_pointer(); + private static native int ffi_sizeof_short(); + private static native int ffi_sizeof_int(); + private static native int ffi_sizeof_long(); + private static native int ffi_sizeof_wchar(); // put these in a separate class to avoid an UnsatisfiedLinkError // when LibFallback is initialized but the library is not present @@ -239,6 +249,11 @@ private NativeConstants() {} static final MemorySegment FLOAT_TYPE = MemorySegment.ofAddress(ffi_type_float()); static final MemorySegment DOUBLE_TYPE = MemorySegment.ofAddress(ffi_type_double()); static final MemorySegment POINTER_TYPE = MemorySegment.ofAddress(ffi_type_pointer()); + static final int SIZEOF_SHORT = ffi_sizeof_short(); + static final int SIZEOF_INT = ffi_sizeof_int(); + static final int SIZEOF_LONG = ffi_sizeof_long(); + static final int SIZEOF_WCHAR = ffi_sizeof_wchar(); + static final MemorySegment VOID_TYPE = MemorySegment.ofAddress(ffi_type_void()); static final short STRUCT_TAG = ffi_type_struct(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64Linker.java index 150687d4078..7cf2d524bff 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64Linker.java @@ -27,15 +27,22 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.ppc64.CallArranger; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; public final class LinuxPPC64Linker extends AbstractLinker { + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); + public static LinuxPPC64Linker getInstance() { final class Holder { private static final LinuxPPC64Linker INSTANCE = new LinuxPPC64Linker(); @@ -62,4 +69,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.BIG_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64leLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64leLinker.java index e92b5abe26a..be4d217d547 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64leLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/ppc64/linux/LinuxPPC64leLinker.java @@ -27,15 +27,22 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.ppc64.CallArranger; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; public final class LinuxPPC64leLinker extends AbstractLinker { + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); + public static LinuxPPC64leLinker getInstance() { final class Holder { private static final LinuxPPC64leLinker INSTANCE = new LinuxPPC64leLinker(); @@ -62,4 +69,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.LITTLE_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java index a6593979e99..1c3558b4742 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java @@ -30,14 +30,21 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; public final class LinuxRISCV64Linker extends AbstractLinker { + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); + public static LinuxRISCV64Linker getInstance() { final class Holder { private static final LinuxRISCV64Linker INSTANCE = new LinuxRISCV64Linker(); @@ -64,4 +71,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.LITTLE_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390Linker.java index ac004b9e1e0..80aa950026e 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390Linker.java @@ -27,14 +27,21 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; public final class LinuxS390Linker extends AbstractLinker { + private static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); + public static LinuxS390Linker getInstance() { final class Holder { private static final LinuxS390Linker INSTANCE = new LinuxS390Linker(); @@ -61,4 +68,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.BIG_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java index 91c3beca229..91a0dc76831 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java @@ -27,17 +27,24 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; /** * ABI implementation based on System V ABI AMD64 supplement v.0.99.6 */ public final class SysVx64Linker extends AbstractLinker { + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); + public static SysVx64Linker getInstance() { final class Holder { private static final SysVx64Linker INSTANCE = new SysVx64Linker(); @@ -64,4 +71,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.LITTLE_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java index 574f2b63411..f262bd6872b 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java @@ -26,17 +26,24 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.SharedUtils; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.nio.ByteOrder; +import java.util.Map; /** * ABI implementation based on Windows ABI AMD64 supplement v.0.99.6 */ public final class Windowsx64Linker extends AbstractLinker { + static final Map CANONICAL_LAYOUTS = + SharedUtils.canonicalLayouts(ValueLayout.JAVA_INT, ValueLayout.JAVA_LONG, ValueLayout.JAVA_CHAR); + public static Windowsx64Linker getInstance() { final class Holder { private static final Windowsx64Linker INSTANCE = new Windowsx64Linker(); @@ -63,4 +70,9 @@ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescrip protected ByteOrder linkerByteOrder() { return ByteOrder.LITTLE_ENDIAN; } + + @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java index 84b879aef07..6c5fba7ea6b 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java @@ -39,8 +39,6 @@ * * @implSpec * This class is immutable, thread-safe and value-based. - * - * @since 19 */ public sealed abstract class AbstractGroupLayout & MemoryLayout> extends AbstractLayout diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java index 10a796a4b18..eb67ad5e3af 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java @@ -53,8 +53,9 @@ public final L withName(String name) { return dup(byteAlignment(), Optional.of(name)); } + @SuppressWarnings("unchecked") public final L withoutName() { - return dup(byteAlignment(), Optional.empty()); + return name.isPresent() ? dup(byteAlignment(), Optional.empty()) : (L) this; } public final Optional name() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java index 807da9cb253..ed11e0b28b9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java @@ -31,16 +31,13 @@ import jdk.internal.reflect.Reflection; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; -import sun.invoke.util.Wrapper; +import java.lang.foreign.AddressLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.AddressLayout; import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; import java.util.Optional; @@ -115,24 +112,6 @@ public boolean equals(Object other) { order.equals(otherValue.order); } - public final VarHandle arrayElementVarHandle(int... shape) { - Objects.requireNonNull(shape); - if (!Utils.isElementAligned((ValueLayout) this)) { - throw new UnsupportedOperationException("Layout alignment greater than its size"); - } - MemoryLayout layout = self(); - List path = new ArrayList<>(); - for (int i = shape.length; i > 0; i--) { - int size = shape[i - 1]; - if (size < 0) throw new IllegalArgumentException("Invalid shape size: " + size); - layout = MemoryLayout.sequenceLayout(size, layout); - path.add(MemoryLayout.PathElement.sequenceElement()); - } - layout = MemoryLayout.sequenceLayout(layout); - path.add(MemoryLayout.PathElement.sequenceElement()); - return layout.varHandle(path.toArray(new MemoryLayout.PathElement[0])); - } - /** * {@return the carrier associated with this value layout} */ @@ -177,7 +156,7 @@ static boolean isValidCarrier(Class carrier) { } @ForceInline - public final VarHandle accessHandle() { + public final VarHandle varHandle() { if (handle == null) { // this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity handle = Utils.makeSegmentViewVarHandle(self()); 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 2fee4f2fb64..71c0fbc16bf 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -64,10 +64,10 @@ * Values should be annotated with the feature's {@code JEP}. */ public enum Feature { - // not used + // not used, but required for interim javac to not warn. VIRTUAL_THREADS, - @JEP(number=442, title="Foreign Function & Memory API", status="Third Preview") FOREIGN, + @JEP(number=430, title="String Templates") STRING_TEMPLATES, @JEP(number=443, title="Unnamed Patterns and Variables") diff --git a/src/java.base/share/classes/jdk/internal/misc/VM.java b/src/java.base/share/classes/jdk/internal/misc/VM.java index 3e7351f6321..9b51cfad458 100644 --- a/src/java.base/share/classes/jdk/internal/misc/VM.java +++ b/src/java.base/share/classes/jdk/internal/misc/VM.java @@ -148,6 +148,7 @@ public static long maxDirectMemory() { // User-controllable flag that determines if direct buffers should be page // aligned. The "-XX:+PageAlignDirectMemory" option can be used to force // buffers, allocated by ByteBuffer.allocateDirect, to be page aligned. + @Stable private static boolean pageAlignDirectMemory; // Returns {@code true} if the direct buffers should be page aligned. This diff --git a/src/java.base/share/classes/jdk/internal/module/Modules.java b/src/java.base/share/classes/jdk/internal/module/Modules.java index 00a1c1ab290..be3f8b63a9b 100644 --- a/src/java.base/share/classes/jdk/internal/module/Modules.java +++ b/src/java.base/share/classes/jdk/internal/module/Modules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -134,6 +134,13 @@ public static void addOpensToAllUnnamed(Module m, String pn) { JLA.addOpensToAllUnnamed(m, pn); } + /** + * Adds native access to all unnamed modules. + */ + public static void addEnableNativeAccessToAllUnnamed() { + JLA.addEnableNativeAccessToAllUnnamed(); + } + /** * Updates module m to use a service. * Same as m2.addUses(service) but without a caller check. diff --git a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java index 81eaf1545ff..f6fa4995388 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java +++ b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.Set; +import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.VM; import jdk.internal.module.ModuleBootstrap; @@ -115,7 +116,10 @@ public static void ensureNativeAccess(Class currentClass, Class owner, Str Module module = currentClass != null ? currentClass.getModule() : ClassLoader.getSystemClassLoader().getUnnamedModule(); - SharedSecrets.getJavaLangAccess().ensureNativeAccess(module, owner, methodName); + class Holder { + static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + } + Holder.JLA.ensureNativeAccess(module, owner, methodName, currentClass); } /** diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 26be8e9b587..bcf7daf8189 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -149,7 +149,7 @@ exports jdk.internal.javac to java.compiler, jdk.compiler, - jdk.incubator.vector, // participates in preview features + jdk.incubator.vector, jdk.jshell; exports jdk.internal.access to java.desktop, diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index d30f61d9e2b..05f797da70f 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -102,6 +102,7 @@ private LauncherHelper() {} private static final String MAIN_CLASS = "Main-Class"; private static final String ADD_EXPORTS = "Add-Exports"; private static final String ADD_OPENS = "Add-Opens"; + private static final String ENABLE_NATIVE_ACCESS = "Enable-Native-Access"; private static StringBuilder outBuf = new StringBuilder(); @@ -632,6 +633,13 @@ static String getMainClassFromJar(String jarname) { if (opens != null) { addExportsOrOpens(opens, true); } + String enableNativeAccess = mainAttrs.getValue(ENABLE_NATIVE_ACCESS); + if (enableNativeAccess != null) { + if (!enableNativeAccess.equals("ALL-UNNAMED")) { + abort(null, "java.launcher.jar.error.illegal.ena.value", enableNativeAccess); + } + Modules.addEnableNativeAccessToAllUnnamed(); + } /* * Hand off to FXHelper if it detects a JavaFX application diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/src/java.base/share/classes/sun/launcher/resources/launcher.properties index 9d5373d0856..f2ec465be26 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -268,6 +268,8 @@ java.launcher.jar.error1=\ java.launcher.jar.error2=manifest not found in {0} java.launcher.jar.error3=no main manifest attribute, in {0} java.launcher.jar.error4=error loading java agent in {0} +java.launcher.jar.error.illegal.ena.value=\ + Error: illegal value \"{0}\" for Enable-Native-Access manifest attribute. Only 'ALL-UNNAMED' is allowed java.launcher.init.error=initialization error java.launcher.javafx.error1=\ Error: The JavaFX launchApplication method has the wrong signature, it\n\ diff --git a/src/java.base/share/native/libfallbackLinker/fallbackLinker.c b/src/java.base/share/native/libfallbackLinker/fallbackLinker.c index 9b3d88dcc0c..e99483adbd5 100644 --- a/src/java.base/share/native/libfallbackLinker/fallbackLinker.c +++ b/src/java.base/share/native/libfallbackLinker/fallbackLinker.c @@ -29,6 +29,7 @@ #include #include +#include #ifdef _WIN64 #include #include @@ -206,3 +207,23 @@ JNIEXPORT jlong JNICALL Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1pointer(JNIEnv* env, jclass cls) { return ptr_to_jlong(&ffi_type_pointer); } + +JNIEXPORT jint JNICALL +Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1short(JNIEnv* env, jclass cls) { + return sizeof(short); +} + +JNIEXPORT jint JNICALL +Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1int(JNIEnv* env, jclass cls) { + return sizeof(int); +} + +JNIEXPORT jint JNICALL +Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1long(JNIEnv* env, jclass cls) { + return sizeof(long); +} + +JNIEXPORT jint JNICALL +Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1wchar(JNIEnv* env, jclass cls) { + return sizeof(wchar_t); +} diff --git a/src/jdk.incubator.vector/share/classes/module-info.java b/src/jdk.incubator.vector/share/classes/module-info.java index 5824bf915d3..2bd9704493b 100644 --- a/src/jdk.incubator.vector/share/classes/module-info.java +++ b/src/jdk.incubator.vector/share/classes/module-info.java @@ -23,8 +23,6 @@ * questions. */ -import jdk.internal.javac.ParticipatesInPreview; - /** * Defines an API for expressing computations that can be reliably compiled * at runtime into SIMD instructions, such as AVX instructions on x64, and @@ -33,7 +31,6 @@ * * @moduleGraph */ -@ParticipatesInPreview module jdk.incubator.vector { exports jdk.incubator.vector; } diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java b/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java index 5c58c6222f3..88e6fcdcf9a 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java @@ -28,8 +28,7 @@ * @library /test/lib / * @requires vm.debug & vm.compiler2.enabled & (os.simpleArch == "x64" | os.arch == "aarch64") * @modules jdk.incubator.vector - * @compile --enable-preview -source ${jdk.version} TestRangeCheckHoistingScaledIV.java - * @run main/othervm --enable-preview compiler.rangechecks.TestRangeCheckHoistingScaledIV + * @run main/othervm compiler.rangechecks.TestRangeCheckHoistingScaledIV */ package compiler.rangechecks; @@ -83,7 +82,7 @@ public static void main(String[] args) { public static void main(String[] args) throws Exception { ProcessBuilder pb = ProcessTools.createTestJvm( - "--enable-preview", "--add-modules", "jdk.incubator.vector", + "--add-modules", "jdk.incubator.vector", "-Xbatch", "-XX:+TraceLoopPredicate", Launcher.class.getName()); OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java b/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java index ddd47c9d56c..49548bd7244 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestIntrinsicBailOut.java @@ -29,7 +29,6 @@ /* * @test - * @enablePreview * @bug 8262998 * @summary Vector API intrinsincs should not modify IR when bailing out * @modules jdk.incubator.vector diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java index c15c38af64d..eb25472370f 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorErgonomics.java @@ -38,42 +38,42 @@ public class TestVectorErgonomics { public static void main(String[] args) throws Throwable { ProcessTools.executeTestJvm("--add-modules=jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", - "-XX:+EnableVectorReboxing", "-Xlog:compilation", "-version", "--enable-preview") + "-XX:+EnableVectorReboxing", "-Xlog:compilation", "-version") .shouldHaveExitValue(0) .shouldContain("EnableVectorReboxing=true"); ProcessTools.executeTestJvm("--add-modules=jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", - "-XX:+EnableVectorAggressiveReboxing", "-Xlog:compilation", "-version", "--enable-preview") + "-XX:+EnableVectorAggressiveReboxing", "-Xlog:compilation", "-version") .shouldHaveExitValue(0) .shouldContain("EnableVectorAggressiveReboxing=true"); ProcessTools.executeTestJvm("--add-modules=jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", - "-XX:-EnableVectorReboxing", "-Xlog:compilation", "-version", "--enable-preview") + "-XX:-EnableVectorReboxing", "-Xlog:compilation", "-version") .shouldHaveExitValue(0) .shouldContain("EnableVectorReboxing=false") .shouldContain("EnableVectorAggressiveReboxing=false"); ProcessTools.executeTestJvm("--add-modules=jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", - "-XX:-EnableVectorAggressiveReboxing", "-Xlog:compilation", "-version", "--enable-preview") + "-XX:-EnableVectorAggressiveReboxing", "-Xlog:compilation", "-version") .shouldHaveExitValue(0) .shouldContain("EnableVectorAggressiveReboxing=false"); ProcessTools.executeTestJvm("--add-modules=jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", - "-XX:-EnableVectorSupport", "-Xlog:compilation", "-version", "--enable-preview") + "-XX:-EnableVectorSupport", "-Xlog:compilation", "-version") .shouldHaveExitValue(0) .shouldContain("EnableVectorSupport=false") .shouldContain("EnableVectorReboxing=false") .shouldContain("EnableVectorAggressiveReboxing=false"); ProcessTools.executeTestJvm("--add-modules=jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", - "-XX:-EnableVectorSupport", "-XX:+EnableVectorReboxing", "-Xlog:compilation", "-version", "--enable-preview") + "-XX:-EnableVectorSupport", "-XX:+EnableVectorReboxing", "-Xlog:compilation", "-version") .shouldHaveExitValue(0) .shouldContain("EnableVectorSupport=false") .shouldContain("EnableVectorReboxing=false") .shouldContain("EnableVectorAggressiveReboxing=false"); ProcessTools.executeTestJvm("--add-modules=jdk.incubator.vector", "-XX:+UnlockExperimentalVMOptions", - "-XX:-EnableVectorSupport", "-XX:+EnableVectorAggressiveReboxing", "-Xlog:compilation", "-version", "--enable-preview") + "-XX:-EnableVectorSupport", "-XX:+EnableVectorAggressiveReboxing", "-Xlog:compilation", "-version") .shouldHaveExitValue(0) .shouldContain("EnableVectorSupport=false") .shouldContain("EnableVectorReboxing=false") diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorMemoryAlias.java b/test/hotspot/jtreg/compiler/vectorapi/VectorMemoryAlias.java index 9dde0aee021..2d2ab614185 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorMemoryAlias.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorMemoryAlias.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Rado Smogura. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,7 +26,6 @@ /* * @test - * @enablePreview * @summary Test if memory ordering is preserved * * @run main/othervm -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java b/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java index e31240c0de2..239f5256405 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -37,7 +37,6 @@ /* * @test id=ZSinglegen * @bug 8260473 - * @enablePreview * @requires vm.gc.ZSinglegen * @modules jdk.incubator.vector * @modules java.base/jdk.internal.vm.annotation @@ -48,7 +47,6 @@ /* * @test id=ZGenerational * @bug 8260473 - * @enablePreview * @requires vm.gc.ZGenerational * @modules jdk.incubator.vector * @modules java.base/jdk.internal.vm.annotation diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX1.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX1.java index 1312ef3c46c..050777505e2 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX1.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,7 +30,6 @@ /* * @test * @bug 8259610 - * @enablePreview * @key randomness * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX2.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX2.java index a963f5b5bab..2c5cfe7de99 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX2.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,7 +30,6 @@ /* * @test * @bug 8259610 - * @enablePreview * @key randomness * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512.java index 10becff9be3..903958943e3 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,7 +30,6 @@ /* * @test * @bug 8259610 - * @enablePreview * @key randomness * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512BW.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512BW.java index 258241fe660..d98379ae800 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512BW.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512BW.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,7 +30,6 @@ /* * @test * @bug 8278623 - * @enablePreview * @key randomness * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512DQ.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512DQ.java index 359e32b6b71..95279423651 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512DQ.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastAVX512DQ.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,7 +30,6 @@ /* * @test * @bug 8259610 - * @enablePreview * @key randomness * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastNeon.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastNeon.java index 74c377eeb07..75a8fada91e 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastNeon.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastNeon.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,7 +30,6 @@ /* * @test * @bug 8259610 - * @enablePreview * @key randomness * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastSVE.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastSVE.java index 48aff2b0ffd..e1cd1f0fdac 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastSVE.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastSVE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -30,7 +30,6 @@ /* * @test * @bug 8259610 - * @enablePreview * @key randomness * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java index 3876da893d6..5891033fbd9 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorReinterpret.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -36,7 +36,6 @@ * @test * @bug 8259610 * @key randomness - * @enablePreview * @modules jdk.incubator.vector * @modules java.base/jdk.internal.misc * @summary Test that vector reinterpret intrinsics work as intended. diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorReshapeHelper.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorReshapeHelper.java index 349429b6c80..a9f2ed54d01 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorReshapeHelper.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/VectorReshapeHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -77,7 +77,7 @@ public static void runMainHelper(Class testClass, Stream t var test = new TestFramework(testClass); test.setDefaultWarmup(1); test.addHelperClasses(VectorReshapeHelper.class); - test.addFlags("--add-modules=jdk.incubator.vector", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", "--enable-preview"); + test.addFlags("--add-modules=jdk.incubator.vector", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED"); test.addFlags(flags); String testMethodNames = testMethods .filter(p -> p.isp().length() <= VectorSpecies.ofLargestShape(p.isp().elementType()).length()) diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java index a0dff95a23f..8004d34f5ce 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -23,7 +23,6 @@ /** * @test - * @enablePreview * @bug 8259937 * @summary guarantee(loc != NULL) failed: missing saved register with native invoke * diff --git a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java index d380419632c..c1e09f058c7 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java +++ b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -42,7 +42,7 @@ public class ClassFileVersionTest { * compilation. If a particular class becomes non-preview, any * currently preview class can be substituted in. */ - private static final Class PREVIEW_API = java.lang.foreign.MemorySegment.class; + private static final Class PREVIEW_API = java.lang.ScopedValue.class; static Method m; public static void testIt(String className, int expectedResult) throws Exception { diff --git a/test/jdk/java/foreign/CompositeLookupTest.java b/test/jdk/java/foreign/CompositeLookupTest.java index 8ca49ef7992..1cc0b35950d 100644 --- a/test/jdk/java/foreign/CompositeLookupTest.java +++ b/test/jdk/java/foreign/CompositeLookupTest.java @@ -34,7 +34,6 @@ /* * @test - * @enablePreview * @run testng CompositeLookupTest */ public class CompositeLookupTest { diff --git a/test/jdk/java/foreign/LibraryLookupTest.java b/test/jdk/java/foreign/LibraryLookupTest.java index 8fec4c53371..dec1a5574ba 100644 --- a/test/jdk/java/foreign/LibraryLookupTest.java +++ b/test/jdk/java/foreign/LibraryLookupTest.java @@ -35,8 +35,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED LibraryLookupTest */ public class LibraryLookupTest { diff --git a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java index de4c49d03b6..c304a139014 100644 --- a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java +++ b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng/othervm MemoryLayoutPrincipalTotalityTest */ diff --git a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java index 70e0aa1f6eb..ecfc4b0da38 100644 --- a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java +++ b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng/othervm MemoryLayoutTypeRetentionTest */ diff --git a/test/jdk/java/foreign/NativeTestHelper.java b/test/jdk/java/foreign/NativeTestHelper.java index a161d687643..24c9db3b59f 100644 --- a/test/jdk/java/foreign/NativeTestHelper.java +++ b/test/jdk/java/foreign/NativeTestHelper.java @@ -86,44 +86,63 @@ public static boolean isPointer(MemoryLayout layout) { return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemorySegment.class; } + public static final Linker LINKER = Linker.nativeLinker(); + // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms. /** * The layout for the {@code bool} C type */ - public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; + public static final ValueLayout.OfBoolean C_BOOL = (ValueLayout.OfBoolean) LINKER.canonicalLayouts().get("bool"); /** * The layout for the {@code char} C type */ - public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; + public static final ValueLayout.OfByte C_CHAR = (ValueLayout.OfByte) LINKER.canonicalLayouts().get("char"); /** * The layout for the {@code short} C type */ - public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT; + public static final ValueLayout.OfShort C_SHORT = (ValueLayout.OfShort) LINKER.canonicalLayouts().get("short"); /** * The layout for the {@code int} C type */ - public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT; + public static final ValueLayout.OfInt C_INT = (ValueLayout.OfInt) LINKER.canonicalLayouts().get("int"); /** * The layout for the {@code long long} C type. */ - public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG; + public static final ValueLayout.OfLong C_LONG_LONG = (ValueLayout.OfLong) LINKER.canonicalLayouts().get("long long"); /** * The layout for the {@code float} C type */ - public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT; + public static final ValueLayout.OfFloat C_FLOAT = (ValueLayout.OfFloat) LINKER.canonicalLayouts().get("float"); /** * The layout for the {@code double} C type */ - public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE; + public static final ValueLayout.OfDouble C_DOUBLE = (ValueLayout.OfDouble) LINKER.canonicalLayouts().get("double"); /** * The {@code T*} native type. */ - public static final AddressLayout C_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(C_CHAR)); - - public static final Linker LINKER = Linker.nativeLinker(); + public static final AddressLayout C_POINTER = ((AddressLayout) LINKER.canonicalLayouts().get("void*")) + .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, C_CHAR)); + /** + * The layout for the {@code size_t} C type + */ + public static final ValueLayout C_SIZE_T = (ValueLayout) LINKER.canonicalLayouts().get("size_t"); + + // Common layout shared by some tests + // struct S_PDI { void* p0; double p1; int p2; }; + public static final MemoryLayout S_PDI_LAYOUT = switch ((int) ValueLayout.ADDRESS.byteSize()) { + case 8 -> MemoryLayout.structLayout( + C_POINTER.withName("p0"), + C_DOUBLE.withName("p1"), + C_INT.withName("p2"), + MemoryLayout.paddingLayout(4)); + case 4 -> MemoryLayout.structLayout( + C_POINTER.withName("p0"), + C_DOUBLE.withName("p1"), + C_INT.withName("p2")); + default -> throw new UnsupportedOperationException("Unsupported address size"); + }; private static final MethodHandle FREE = LINKER.downcallHandle( LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(C_POINTER)); @@ -248,8 +267,8 @@ private static Consumer initField(RandomGenerator random, MemorySegment } else { VarHandle accessor = containerLayout.varHandle(fieldPath); //set value - accessor.set(container, fieldValue.value()); - return actual -> fieldCheck.accept(accessor.get((MemorySegment) actual)); + accessor.set(container, 0L, fieldValue.value()); + return actual -> fieldCheck.accept(accessor.get((MemorySegment) actual, 0L)); } } @@ -257,7 +276,7 @@ private static UnaryOperator slicer(MemoryLayout containerLayout, MethodHandle slicer = containerLayout.sliceHandle(fieldPath); return container -> { try { - return (MemorySegment) slicer.invokeExact(container); + return (MemorySegment) slicer.invokeExact(container, 0L); } catch (Throwable e) { throw new IllegalStateException(e); } diff --git a/test/jdk/java/foreign/SafeFunctionAccessTest.java b/test/jdk/java/foreign/SafeFunctionAccessTest.java index 139c3b3a26b..f5715370a9b 100644 --- a/test/jdk/java/foreign/SafeFunctionAccessTest.java +++ b/test/jdk/java/foreign/SafeFunctionAccessTest.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED SafeFunctionAccessTest */ diff --git a/test/jdk/java/foreign/StdLibTest.java b/test/jdk/java/foreign/StdLibTest.java index 360bb501bbb..7bb8a29b0c0 100644 --- a/test/jdk/java/foreign/StdLibTest.java +++ b/test/jdk/java/foreign/StdLibTest.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED StdLibTest */ @@ -51,7 +49,6 @@ import static org.testng.Assert.*; -@Test public class StdLibTest extends NativeTestHelper { final static Linker abi = Linker.nativeLinker(); @@ -121,16 +118,20 @@ void test_rand() throws Throwable { @Test(dataProvider = "printfArgs") void test_printf(List args) throws Throwable { - String formatArgs = args.stream() - .map(a -> a.format) + String javaFormatArgs = args.stream() + .map(a -> a.javaFormat) + .collect(Collectors.joining(",")); + String nativeFormatArgs = args.stream() + .map(a -> a.nativeFormat) .collect(Collectors.joining(",")); - String formatString = "hello(" + formatArgs + ")\n"; + String javaFormatString = "hello(" + javaFormatArgs + ")\n"; + String nativeFormatString = "hello(" + nativeFormatArgs + ")\n"; - String expected = String.format(formatString, args.stream() + String expected = String.format(javaFormatString, args.stream() .map(a -> a.javaValue).toArray()); - int found = stdLibHelper.printf(formatString, args); + int found = stdLibHelper.printf(nativeFormatString, args); assertEquals(found, expected.length()); } @@ -156,8 +157,9 @@ static class StdLibHelper { final static MethodHandle gmtime = abi.downcallHandle(abi.defaultLookup().find("gmtime").get(), FunctionDescriptor.of(C_POINTER.withTargetLayout(Tm.LAYOUT), C_POINTER)); + // void qsort( void *ptr, size_t count, size_t size, int (*comp)(const void *, const void *) ); final static MethodHandle qsort = abi.downcallHandle(abi.defaultLookup().find("qsort").get(), - FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER)); + FunctionDescriptor.ofVoid(C_POINTER, C_SIZE_T, C_SIZE_T, C_POINTER)); final static FunctionDescriptor qsortComparFunction = FunctionDescriptor.of(C_INT, C_POINTER.withTargetLayout(C_INT), C_POINTER.withTargetLayout(C_INT)); @@ -187,30 +189,30 @@ static class StdLibHelper { String strcat(String s1, String s2) throws Throwable { try (var arena = Arena.ofConfined()) { MemorySegment buf = arena.allocate(s1.length() + s2.length() + 1); - buf.setUtf8String(0, s1); - MemorySegment other = arena.allocateUtf8String(s2); - return ((MemorySegment)strcat.invokeExact(buf, other)).getUtf8String(0); + buf.setString(0, s1); + MemorySegment other = arena.allocateFrom(s2); + return ((MemorySegment)strcat.invokeExact(buf, other)).getString(0); } } int strcmp(String s1, String s2) throws Throwable { try (var arena = Arena.ofConfined()) { - MemorySegment ns1 = arena.allocateUtf8String(s1); - MemorySegment ns2 = arena.allocateUtf8String(s2); + MemorySegment ns1 = arena.allocateFrom(s1); + MemorySegment ns2 = arena.allocateFrom(s2); return (int)strcmp.invokeExact(ns1, ns2); } } int puts(String msg) throws Throwable { try (var arena = Arena.ofConfined()) { - MemorySegment s = arena.allocateUtf8String(msg); + MemorySegment s = arena.allocateFrom(msg); return (int)puts.invokeExact(s); } } int strlen(String msg) throws Throwable { try (var arena = Arena.ofConfined()) { - MemorySegment s = arena.allocateUtf8String(msg); + MemorySegment s = arena.allocateFrom(msg); return (int)strlen.invokeExact(s); } } @@ -277,12 +279,16 @@ boolean isdst() { int[] qsort(int[] arr) throws Throwable { //init native array try (var arena = Arena.ofConfined()) { - MemorySegment nativeArr = arena.allocateArray(C_INT, arr); + MemorySegment nativeArr = arena.allocateFrom(C_INT, arr); //call qsort MemorySegment qsortUpcallStub = abi.upcallStub(qsortCompar, qsortComparFunction, arena); - qsort.invokeExact(nativeArr, (long)arr.length, C_INT.byteSize(), qsortUpcallStub); + // both of these fit in an int + // automatically widen them to long on x64 + int count = arr.length; + int size = (int) C_INT.byteSize(); + qsort.invoke(nativeArr, count, size, qsortUpcallStub); //convert back to Java array return nativeArr.toArray(C_INT); @@ -300,7 +306,7 @@ int rand() throws Throwable { int printf(String format, List args) throws Throwable { try (var arena = Arena.ofConfined()) { - MemorySegment formatStr = arena.allocateUtf8String(format); + MemorySegment formatStr = arena.allocateFrom(format); return (int)specializedPrintf(args).invokeExact(formatStr, args.stream().map(a -> a.nativeValue(arena)).toArray()); } @@ -378,21 +384,24 @@ public static Object[][] printfArgs() { } enum PrintfArg { - INT(int.class, C_INT, "%d", arena -> 42, 42), - LONG(long.class, C_LONG_LONG, "%d", arena -> 84L, 84L), - DOUBLE(double.class, C_DOUBLE, "%.4f", arena -> 1.2345d, 1.2345d), - STRING(MemorySegment.class, C_POINTER, "%s", arena -> arena.allocateUtf8String("str"), "str"); + INT(int.class, C_INT, "%d", "%d", arena -> 42, 42), + LONG(long.class, C_LONG_LONG, "%lld", "%d", arena -> 84L, 84L), + DOUBLE(double.class, C_DOUBLE, "%.4f", "%.4f", arena -> 1.2345d, 1.2345d), + STRING(MemorySegment.class, C_POINTER, "%s", "%s", arena -> arena.allocateFrom("str"), "str"); final Class carrier; final ValueLayout layout; - final String format; + final String nativeFormat; + final String javaFormat; final Function nativeValueFactory; final Object javaValue; - PrintfArg(Class carrier, L layout, String format, Function nativeValueFactory, Object javaValue) { + PrintfArg(Class carrier, L layout, String nativeFormat, String javaFormat, + Function nativeValueFactory, Object javaValue) { this.carrier = carrier; this.layout = layout; - this.format = format; + this.nativeFormat = nativeFormat; + this.javaFormat = javaFormat; this.nativeValueFactory = nativeValueFactory; this.javaValue = javaValue; } diff --git a/test/jdk/java/foreign/TestAccessModes.java b/test/jdk/java/foreign/TestAccessModes.java new file mode 100644 index 00000000000..9ee5020fd9e --- /dev/null +++ b/test/jdk/java/foreign/TestAccessModes.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAccessModes + * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAccessModes + * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAccessModes + * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAccessModes + */ + +import java.lang.foreign.AddressLayout; +import java.lang.foreign.Arena; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; +import java.lang.invoke.VarHandle.AccessMode; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import org.testng.annotations.*; + +import static org.testng.Assert.*; +public class TestAccessModes { + + @Test(dataProvider = "segmentsAndLayoutsAndModes") + public void testAccessModes(MemorySegment segment, ValueLayout layout, AccessMode mode) throws Throwable { + VarHandle varHandle = layout.varHandle(); + MethodHandle methodHandle = varHandle.toMethodHandle(mode); + boolean compatible = AccessModeKind.supportedModes(layout).contains(AccessModeKind.of(mode)); + try { + Object o = methodHandle.invokeWithArguments(makeArgs(segment, varHandle.accessModeType(mode))); + assertTrue(compatible); + } catch (UnsupportedOperationException ex) { + assertFalse(compatible); + } catch (IllegalArgumentException ex) { + // access is unaligned, but access mode is supported + assertTrue(compatible); + } + } + + Object[] makeArgs(MemorySegment segment, MethodType type) throws Throwable { + List args = new ArrayList<>(); + args.add(segment); + for (Class argType : type.dropParameterTypes(0, 1).parameterList()) { + args.add(defaultValue(argType)); + } + return args.toArray(); + } + + Object defaultValue(Class clazz) throws Throwable { + if (clazz == MemorySegment.class) { + return MemorySegment.NULL; + } else if (clazz.isPrimitive()) { + return MethodHandles.zero(clazz).invoke(); + } else { + throw new UnsupportedOperationException(); + } + } + + /* + * See the javadoc of MemoryLayout::varHandle. + */ + enum AccessModeKind { + PLAIN, + READ_WRITE, + ATOMIC_UPDATE, + ATOMIC_NUMERIC_UPDATE, + ATOMIC_BITWISE_UPDATE; + + static AccessModeKind of(AccessMode mode) { + return switch (mode) { + case GET, SET -> PLAIN; + case GET_ACQUIRE, GET_OPAQUE, GET_VOLATILE, SET_VOLATILE, + SET_OPAQUE, SET_RELEASE -> READ_WRITE; + case GET_AND_SET, GET_AND_SET_ACQUIRE, GET_AND_SET_RELEASE, + WEAK_COMPARE_AND_SET, WEAK_COMPARE_AND_SET_RELEASE, + WEAK_COMPARE_AND_SET_ACQUIRE, WEAK_COMPARE_AND_SET_PLAIN, + COMPARE_AND_EXCHANGE, COMPARE_AND_EXCHANGE_ACQUIRE, + COMPARE_AND_EXCHANGE_RELEASE, COMPARE_AND_SET -> ATOMIC_UPDATE; + case GET_AND_ADD, GET_AND_ADD_ACQUIRE, GET_AND_ADD_RELEASE -> ATOMIC_NUMERIC_UPDATE; + default -> ATOMIC_BITWISE_UPDATE; + }; + } + + static Set supportedModes(ValueLayout layout) { + Set supportedModes = EnumSet.noneOf(AccessModeKind.class); + supportedModes.add(PLAIN); + if (layout.byteAlignment() >= layout.byteSize()) { + supportedModes.add(READ_WRITE); + if (layout instanceof ValueLayout.OfInt || layout instanceof ValueLayout.OfLong || + layout instanceof ValueLayout.OfFloat || layout instanceof ValueLayout.OfDouble || + layout instanceof AddressLayout) { + supportedModes.add(ATOMIC_UPDATE); + } + if (layout instanceof ValueLayout.OfInt || layout instanceof ValueLayout.OfLong || + layout instanceof AddressLayout) { + supportedModes.add(ATOMIC_NUMERIC_UPDATE); + supportedModes.add(ATOMIC_BITWISE_UPDATE); + } + } + return supportedModes; + } + } + + static MemoryLayout[] layouts() { + MemoryLayout[] valueLayouts = { + ValueLayout.JAVA_BOOLEAN, + ValueLayout.JAVA_CHAR, + ValueLayout.JAVA_BYTE, + ValueLayout.JAVA_SHORT, + ValueLayout.JAVA_INT, + ValueLayout.JAVA_FLOAT, + ValueLayout.JAVA_LONG, + ValueLayout.JAVA_DOUBLE, + ValueLayout.ADDRESS + }; + List layouts = new ArrayList<>(); + for (MemoryLayout layout : valueLayouts) { + for (int align : new int[] { 1, 2, 4, 8 }) { + layouts.add(layout.withByteAlignment(align)); + } + } + return layouts.toArray(new MemoryLayout[0]); + } + + static MemorySegment[] segments() { + return new MemorySegment[]{ + Arena.ofAuto().allocate(8), + MemorySegment.ofArray(new byte[8]), + MemorySegment.ofArray(new char[4]), + MemorySegment.ofArray(new short[4]), + MemorySegment.ofArray(new int[2]), + MemorySegment.ofArray(new float[2]), + MemorySegment.ofArray(new long[1]), + MemorySegment.ofArray(new double[1]) + }; + } + + @DataProvider(name = "segmentsAndLayoutsAndModes") + static Object[][] segmentsAndLayoutsAndModes() { + List segmentsAndLayouts = new ArrayList<>(); + for (MemorySegment segment : segments()) { + for (MemoryLayout layout : layouts()) { + for (AccessMode mode : AccessMode.values()) { + segmentsAndLayouts.add(new Object[]{segment, layout, mode}); + } + } + } + return segmentsAndLayouts.toArray(new Object[0][]); + } + +} diff --git a/test/jdk/java/foreign/TestAdaptVarHandles.java b/test/jdk/java/foreign/TestAdaptVarHandles.java index 5074b8d793b..2849b308160 100644 --- a/test/jdk/java/foreign/TestAdaptVarHandles.java +++ b/test/jdk/java/foreign/TestAdaptVarHandles.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAdaptVarHandles * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAdaptVarHandles * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAdaptVarHandles @@ -83,11 +82,12 @@ public class TestAdaptVarHandles { } } - static final VarHandle intHandleIndexed = ValueLayout.JAVA_INT.arrayElementVarHandle(); + static final VarHandle intHandleIndexed = MethodHandles.collectCoordinates(ValueLayout.JAVA_INT.varHandle(), + 1, MethodHandles.insertArguments(ValueLayout.JAVA_INT.scaleHandle(), 0, 0L)); - static final VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); + static final VarHandle intHandle = MethodHandles.insertCoordinates(ValueLayout.JAVA_INT.varHandle(), 1, 0L); - static final VarHandle floatHandle = ValueLayout.JAVA_FLOAT.varHandle(); + static final VarHandle floatHandle = MethodHandles.insertCoordinates(ValueLayout.JAVA_FLOAT.varHandle(), 1, 0L); @Test public void testFilterValue() throws Throwable { @@ -96,16 +96,16 @@ public void testFilterValue() throws Throwable { MemorySegment segment = scope.allocate(layout); VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, S2I, I2S); - i2SHandle.set(segment, "1"); - String oldValue = (String)i2SHandle.getAndAdd(segment, "42"); + i2SHandle.set(segment, 0L, "1"); + String oldValue = (String)i2SHandle.getAndAdd(segment, 0L, "42"); assertEquals(oldValue, "1"); - String value = (String)i2SHandle.get(segment); + String value = (String)i2SHandle.get(segment, 0L); assertEquals(value, "43"); - boolean swapped = (boolean)i2SHandle.compareAndSet(segment, "43", "12"); + boolean swapped = (boolean)i2SHandle.compareAndSet(segment, 0L, "43", "12"); assertTrue(swapped); - oldValue = (String)i2SHandle.compareAndExchange(segment, "12", "42"); + oldValue = (String)i2SHandle.compareAndExchange(segment, 0L, "12", "42"); assertEquals(oldValue, "12"); - value = (String)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment); + value = (String)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, 0L); assertEquals(value, "42"); } @@ -117,17 +117,17 @@ public void testFilterValueComposite() throws Throwable { VarHandle intHandle = layout.varHandle(); MethodHandle CTX_S2I = MethodHandles.dropArguments(S2I, 0, String.class, String.class); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, CTX_S2I, CTX_I2S); - i2SHandle = MethodHandles.insertCoordinates(i2SHandle, 1, "a", "b"); - i2SHandle.set(segment, "1"); - String oldValue = (String)i2SHandle.getAndAdd(segment, "42"); + i2SHandle = MethodHandles.insertCoordinates(i2SHandle, 2, "a", "b"); + i2SHandle.set(segment, 0L, "1"); + String oldValue = (String)i2SHandle.getAndAdd(segment, 0L, "42"); assertEquals(oldValue, "ab1"); - String value = (String)i2SHandle.get(segment); + String value = (String)i2SHandle.get(segment, 0L); assertEquals(value, "ab43"); - boolean swapped = (boolean)i2SHandle.compareAndSet(segment, "43", "12"); + boolean swapped = (boolean)i2SHandle.compareAndSet(segment, 0L, "43", "12"); assertTrue(swapped); - oldValue = (String)i2SHandle.compareAndExchange(segment, "12", "42"); + oldValue = (String)i2SHandle.compareAndExchange(segment, 0L, "12", "42"); assertEquals(oldValue, "ab12"); - value = (String)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment); + value = (String)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, 0L); assertEquals(value, "ab42"); } @@ -138,16 +138,16 @@ public void testFilterValueLoose() throws Throwable { MemorySegment segment = scope.allocate(layout); VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, O2I, I2O); - i2SHandle.set(segment, "1"); - String oldValue = (String)i2SHandle.getAndAdd(segment, "42"); + i2SHandle.set(segment, 0L, "1"); + String oldValue = (String)i2SHandle.getAndAdd(segment, 0L, "42"); assertEquals(oldValue, "1"); - String value = (String)i2SHandle.get(segment); + String value = (String)i2SHandle.get(segment, 0L); assertEquals(value, "43"); - boolean swapped = (boolean)i2SHandle.compareAndSet(segment, "43", "12"); + boolean swapped = (boolean)i2SHandle.compareAndSet(segment, 0L, "43", "12"); assertTrue(swapped); - oldValue = (String)i2SHandle.compareAndExchange(segment, "12", "42"); + oldValue = (String)i2SHandle.compareAndExchange(segment, 0L, "12", "42"); assertEquals(oldValue, "12"); - value = (String)(Object)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment); + value = (String)(Object)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment, 0L); assertEquals(value, "42"); } @@ -194,8 +194,8 @@ public void testBadFilterBoxHandleException() { VarHandle vh = MethodHandles.filterValue(intHandle, S2I, I2S_EX); try (Arena arena = Arena.ofConfined()) { MemorySegment seg = arena.allocate(ValueLayout.JAVA_INT); - vh.set(seg, "42"); - String x = (String) vh.get(seg); // should throw + vh.set(seg, 0L, "42"); + String x = (String) vh.get(seg, 0L); // should throw } } @@ -205,7 +205,7 @@ public void testBadFilterUnboxHandleException() { VarHandle vh = MethodHandles.filterValue(intHandle, S2I_EX, I2S); try (Arena arena = Arena.ofConfined()) { MemorySegment seg = arena.allocate(ValueLayout.JAVA_INT); - vh.set(seg, "42"); // should throw + vh.set(seg, 0L, "42"); // should throw } } diff --git a/test/jdk/java/foreign/TestAddressDereference.java b/test/jdk/java/foreign/TestAddressDereference.java index 8756afce29e..6dc9575e5ae 100644 --- a/test/jdk/java/foreign/TestAddressDereference.java +++ b/test/jdk/java/foreign/TestAddressDereference.java @@ -23,9 +23,7 @@ /* * @test - * @enablePreview * @library ../ /test/lib - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestAddressDereference */ @@ -40,6 +38,8 @@ import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.testng.annotations.*; @@ -184,18 +184,23 @@ enum LayoutKind { this.layout = segment; } + private static final Pattern LAYOUT_PATTERN = Pattern.compile("^(?\\d+%)?(?[azcsifjdAZCSIFJD])\\d+$"); + static LayoutKind parse(String layoutString) { - return switch (layoutString.charAt(0)) { - case 'A','a' -> ADDRESS; - case 'z','Z' -> BOOL; - case 'c','C' -> CHAR; - case 's','S' -> SHORT; - case 'i','I' -> INT; - case 'f','F' -> FLOAT; - case 'j','J' -> LONG; - case 'd','D' -> DOUBLE; - default -> throw new AssertionError("Invalid layout string: " + layoutString); - }; + Matcher matcher = LAYOUT_PATTERN.matcher(layoutString); + if (matcher.matches()) { + switch (matcher.group("char")) { + case "A","a": return ADDRESS; + case "z","Z": return BOOL; + case "c","C": return CHAR; + case "s","S": return SHORT; + case "i","I": return INT; + case "f","F": return FLOAT; + case "j","J": return LONG; + case "d","D": return DOUBLE; + }; + } + throw new AssertionError("Invalid layout string: " + layoutString); } } } diff --git a/test/jdk/java/foreign/TestArrayCopy.java b/test/jdk/java/foreign/TestArrayCopy.java index a2302249d3a..dfe5c343f73 100644 --- a/test/jdk/java/foreign/TestArrayCopy.java +++ b/test/jdk/java/foreign/TestArrayCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -23,12 +23,15 @@ /* * @test - * @enablePreview * @run testng TestArrayCopy */ +import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.nio.ByteOrder; import java.util.ArrayList; @@ -288,9 +291,14 @@ public static MemorySegment srcSegment(int bytesLength) { return MemorySegment.ofArray(arr); } + private static VarHandle arrayVarHandle(ValueLayout layout) { + return MethodHandles.collectCoordinates(layout.varHandle(), + 1, MethodHandles.insertArguments(layout.scaleHandle(), 0, 0L)); + } + public static MemorySegment truthSegment(MemorySegment srcSeg, CopyHelper helper, int indexShifts, CopyMode mode) { - VarHandle indexedHandleNO = helper.elementLayout.withOrder(NATIVE_ORDER).arrayElementVarHandle(); - VarHandle indexedHandleNNO = helper.elementLayout.withOrder(NON_NATIVE_ORDER).arrayElementVarHandle(); + VarHandle indexedHandleNO = arrayVarHandle(helper.elementLayout.withOrder(NATIVE_ORDER)); + VarHandle indexedHandleNNO = arrayVarHandle(helper.elementLayout.withOrder(NON_NATIVE_ORDER)); MemorySegment dstSeg = MemorySegment.ofArray(srcSeg.toArray(JAVA_BYTE)); int indexLength = (int) dstSeg.byteSize() / (int)helper.elementLayout.byteSize(); if (mode.direction) { diff --git a/test/jdk/java/foreign/TestArrays.java b/test/jdk/java/foreign/TestArrays.java index 603b79e8e94..4406db36750 100644 --- a/test/jdk/java/foreign/TestArrays.java +++ b/test/jdk/java/foreign/TestArrays.java @@ -24,13 +24,15 @@ /* * @test - * @enablePreview * @run testng/othervm --enable-native-access=ALL-UNNAMED TestArrays */ import java.lang.foreign.*; import java.lang.foreign.MemoryLayout.PathElement; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -144,34 +146,34 @@ public void testArrayFromClosedSegment(MemoryLayout layout, Function byteInitializer = - (base) -> initBytes(base, bytes, (addr, pos) -> byteHandle.set(addr, pos, (byte)(long)pos)); + (base) -> initBytes(base, bytes, (addr, pos) -> byteHandle.set(addr, 0L, pos, (byte)(long)pos)); Consumer charInitializer = - (base) -> initBytes(base, chars, (addr, pos) -> charHandle.set(addr, pos, (char)(long)pos)); + (base) -> initBytes(base, chars, (addr, pos) -> charHandle.set(addr, 0L, pos, (char)(long)pos)); Consumer shortInitializer = - (base) -> initBytes(base, shorts, (addr, pos) -> shortHandle.set(addr, pos, (short)(long)pos)); + (base) -> initBytes(base, shorts, (addr, pos) -> shortHandle.set(addr, 0L, pos, (short)(long)pos)); Consumer intInitializer = - (base) -> initBytes(base, ints, (addr, pos) -> intHandle.set(addr, pos, (int)(long)pos)); + (base) -> initBytes(base, ints, (addr, pos) -> intHandle.set(addr, 0L, pos, (int)(long)pos)); Consumer floatInitializer = - (base) -> initBytes(base, floats, (addr, pos) -> floatHandle.set(addr, pos, (float)(long)pos)); + (base) -> initBytes(base, floats, (addr, pos) -> floatHandle.set(addr, 0L, pos, (float)(long)pos)); Consumer longInitializer = - (base) -> initBytes(base, longs, (addr, pos) -> longHandle.set(addr, pos, (long)pos)); + (base) -> initBytes(base, longs, (addr, pos) -> longHandle.set(addr, 0L, pos, (long)pos)); Consumer doubleInitializer = - (base) -> initBytes(base, doubles, (addr, pos) -> doubleHandle.set(addr, pos, (double)(long)pos)); + (base) -> initBytes(base, doubles, (addr, pos) -> doubleHandle.set(addr, 0L, pos, (double)(long)pos)); Consumer byteChecker = - (base) -> checkBytes(base, bytes, s -> s.toArray(JAVA_BYTE), (addr, pos) -> (byte)byteHandle.get(addr, pos)); + (base) -> checkBytes(base, bytes, s -> s.toArray(JAVA_BYTE), (addr, pos) -> (byte)byteHandle.get(addr, 0L, pos)); Consumer shortChecker = - (base) -> checkBytes(base, shorts, s -> s.toArray(JAVA_SHORT), (addr, pos) -> (short)shortHandle.get(addr, pos)); + (base) -> checkBytes(base, shorts, s -> s.toArray(JAVA_SHORT), (addr, pos) -> (short)shortHandle.get(addr, 0L, pos)); Consumer charChecker = - (base) -> checkBytes(base, chars, s -> s.toArray(JAVA_CHAR), (addr, pos) -> (char)charHandle.get(addr, pos)); + (base) -> checkBytes(base, chars, s -> s.toArray(JAVA_CHAR), (addr, pos) -> (char)charHandle.get(addr, 0L, pos)); Consumer intChecker = - (base) -> checkBytes(base, ints, s -> s.toArray(JAVA_INT), (addr, pos) -> (int)intHandle.get(addr, pos)); + (base) -> checkBytes(base, ints, s -> s.toArray(JAVA_INT), (addr, pos) -> (int)intHandle.get(addr, 0L, pos)); Consumer floatChecker = - (base) -> checkBytes(base, floats, s -> s.toArray(JAVA_FLOAT), (addr, pos) -> (float)floatHandle.get(addr, pos)); + (base) -> checkBytes(base, floats, s -> s.toArray(JAVA_FLOAT), (addr, pos) -> (float)floatHandle.get(addr, 0L, pos)); Consumer longChecker = - (base) -> checkBytes(base, longs, s -> s.toArray(JAVA_LONG), (addr, pos) -> (long)longHandle.get(addr, pos)); + (base) -> checkBytes(base, longs, s -> s.toArray(JAVA_LONG), (addr, pos) -> (long)longHandle.get(addr, 0L, pos)); Consumer doubleChecker = - (base) -> checkBytes(base, doubles, s -> s.toArray(JAVA_DOUBLE), (addr, pos) -> (double)doubleHandle.get(addr, pos)); + (base) -> checkBytes(base, doubles, s -> s.toArray(JAVA_DOUBLE), (addr, pos) -> (double)doubleHandle.get(addr, 0L, pos)); return new Object[][]{ {byteInitializer, byteChecker, bytes}, diff --git a/test/jdk/java/foreign/TestByteBuffer.java b/test/jdk/java/foreign/TestByteBuffer.java index 53640d39c96..1c920239f77 100644 --- a/test/jdk/java/foreign/TestByteBuffer.java +++ b/test/jdk/java/foreign/TestByteBuffer.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules java.base/sun.nio.ch java.base/jdk.internal.foreign * @run testng/othervm/timeout=600 --enable-native-access=ALL-UNNAMED TestByteBuffer */ @@ -122,8 +121,8 @@ public class TestByteBuffer { static void initTuples(MemorySegment base, long count) { for (long i = 0; i < count ; i++) { - indexHandle.set(base, i, (int)i); - valueHandle.set(base, i, (float)(i / 500f)); + indexHandle.set(base, 0L, i, (int)i); + valueHandle.set(base, 0L, i, (float)(i / 500f)); } } @@ -131,8 +130,8 @@ static void checkTuples(MemorySegment base, ByteBuffer bb, long count) { for (long i = 0; i < count ; i++) { int index; float value; - assertEquals(index = bb.getInt(), (int)indexHandle.get(base, i)); - assertEquals(value = bb.getFloat(), (float)valueHandle.get(base, i)); + assertEquals(index = bb.getInt(), (int)indexHandle.get(base, 0L, i)); + assertEquals(value = bb.getFloat(), (float)valueHandle.get(base, 0L, i)); assertEquals(value, index / 500f); } } diff --git a/test/jdk/java/foreign/TestClassLoaderFindNative.java b/test/jdk/java/foreign/TestClassLoaderFindNative.java index 44ec8732ed4..53f6de31d83 100644 --- a/test/jdk/java/foreign/TestClassLoaderFindNative.java +++ b/test/jdk/java/foreign/TestClassLoaderFindNative.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestClassLoaderFindNative */ diff --git a/test/jdk/java/foreign/TestDereferencePath.java b/test/jdk/java/foreign/TestDereferencePath.java index 1c129032053..1b26cce9c6f 100644 --- a/test/jdk/java/foreign/TestDereferencePath.java +++ b/test/jdk/java/foreign/TestDereferencePath.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @run testng TestDereferencePath */ @@ -73,7 +72,7 @@ public void testSingle() { b.set(ValueLayout.ADDRESS, 0, c); c.set(ValueLayout.JAVA_INT, 0, 42); // dereference - int val = (int) abcx.get(a); + int val = (int) abcx.get(a, 0L); assertEquals(val, 42); } } @@ -98,8 +97,8 @@ public void testMulti() { try (Arena arena = Arena.ofConfined()) { // init structs MemorySegment a = arena.allocate(A); - MemorySegment b = arena.allocateArray(B, 2); - MemorySegment c = arena.allocateArray(C, 4); + MemorySegment b = arena.allocate(B, 2); + MemorySegment c = arena.allocate(C, 4); // init struct fields a.set(ValueLayout.ADDRESS, 0, b); b.set(ValueLayout.ADDRESS, 0, c); @@ -109,13 +108,13 @@ public void testMulti() { c.setAtIndex(ValueLayout.JAVA_INT, 2, 3); c.setAtIndex(ValueLayout.JAVA_INT, 3, 4); // dereference - int val00 = (int) abcx_multi.get(a, 0, 0); // a->b[0]->c[0] = 1 + int val00 = (int) abcx_multi.get(a, 0L, 0, 0); // a->b[0]->c[0] = 1 assertEquals(val00, 1); - int val10 = (int) abcx_multi.get(a, 1, 0); // a->b[1]->c[0] = 3 + int val10 = (int) abcx_multi.get(a, 0L, 1, 0); // a->b[1]->c[0] = 3 assertEquals(val10, 3); - int val01 = (int) abcx_multi.get(a, 0, 1); // a->b[0]->c[1] = 2 + int val01 = (int) abcx_multi.get(a, 0L, 0, 1); // a->b[0]->c[1] = 2 assertEquals(val01, 2); - int val11 = (int) abcx_multi.get(a, 1, 1); // a->b[1]->c[1] = 4 + int val11 = (int) abcx_multi.get(a, 0L, 1, 1); // a->b[1]->c[1] = 4 assertEquals(val11, 4); } } @@ -152,7 +151,7 @@ void badDerefMisAligned() { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(struct.byteSize() + 1).asSlice(1); VarHandle vhX = struct.varHandle(PathElement.groupElement("x"), PathElement.dereferenceElement()); - vhX.set(segment, 42); // should throw + vhX.set(segment, 0L, 42); // should throw } } } diff --git a/test/jdk/java/foreign/TestDowncallScope.java b/test/jdk/java/foreign/TestDowncallScope.java index 15ba35e6fb5..9cd42f9050f 100644 --- a/test/jdk/java/foreign/TestDowncallScope.java +++ b/test/jdk/java/foreign/TestDowncallScope.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * diff --git a/test/jdk/java/foreign/TestDowncallStack.java b/test/jdk/java/foreign/TestDowncallStack.java index 6279922766b..28e0aac19db 100644 --- a/test/jdk/java/foreign/TestDowncallStack.java +++ b/test/jdk/java/foreign/TestDowncallStack.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * diff --git a/test/jdk/java/foreign/TestFallbackLookup.java b/test/jdk/java/foreign/TestFallbackLookup.java index c284222f006..5cc78bf747c 100644 --- a/test/jdk/java/foreign/TestFallbackLookup.java +++ b/test/jdk/java/foreign/TestFallbackLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm -Dos.name=Windows --enable-native-access=ALL-UNNAMED TestFallbackLookup */ diff --git a/test/jdk/java/foreign/TestFree.java b/test/jdk/java/foreign/TestFree.java index b14aa4732fb..31e9d9906e1 100644 --- a/test/jdk/java/foreign/TestFree.java +++ b/test/jdk/java/foreign/TestFree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @bug 8248421 * @summary SystemCLinker should have a way to free memory allocated outside Java * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFree @@ -39,7 +38,7 @@ public void test() throws Throwable { MemorySegment addr = allocateMemory(str.length() + 1); addr.copyFrom(MemorySegment.ofArray(str.getBytes())); addr.set(C_CHAR, str.length(), (byte)0); - assertEquals(str, addr.getUtf8String(0)); + assertEquals(str, addr.getString(0)); freeMemory(addr); } } diff --git a/test/jdk/java/foreign/TestFunctionDescriptor.java b/test/jdk/java/foreign/TestFunctionDescriptor.java index 62cb31b1d5d..f4f9290c97d 100644 --- a/test/jdk/java/foreign/TestFunctionDescriptor.java +++ b/test/jdk/java/foreign/TestFunctionDescriptor.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFunctionDescriptor */ diff --git a/test/jdk/java/foreign/TestHFA.java b/test/jdk/java/foreign/TestHFA.java index 00aa328f1ce..33ed1f9e846 100644 --- a/test/jdk/java/foreign/TestHFA.java +++ b/test/jdk/java/foreign/TestHFA.java @@ -25,8 +25,6 @@ /* * @test * @summary Test passing of Homogeneous Float Aggregates. - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * * @run testng/othervm --enable-native-access=ALL-UNNAMED TestHFA */ diff --git a/test/jdk/java/foreign/TestHandshake.java b/test/jdk/java/foreign/TestHandshake.java index 13d9f9608de..4dc96ee9b3b 100644 --- a/test/jdk/java/foreign/TestHandshake.java +++ b/test/jdk/java/foreign/TestHandshake.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules java.base/jdk.internal.vm.annotation java.base/jdk.internal.misc * @key randomness * @run testng/othervm TestHandshake diff --git a/test/jdk/java/foreign/TestHeapAlignment.java b/test/jdk/java/foreign/TestHeapAlignment.java index 60805d51063..99f09611914 100644 --- a/test/jdk/java/foreign/TestHeapAlignment.java +++ b/test/jdk/java/foreign/TestHeapAlignment.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestHeapAlignment */ @@ -45,11 +43,11 @@ public class TestHeapAlignment { @Test(dataProvider = "layouts") public void testHeapAlignment(MemorySegment segment, int align, Object val, Object arr, ValueLayout layout, Function segmentFactory) { - assertAligned(align, layout, () -> layout.varHandle().get(segment)); - assertAligned(align, layout, () -> layout.varHandle().set(segment, val)); + assertAligned(align, layout, () -> layout.varHandle().get(segment, 0L)); + assertAligned(align, layout, () -> layout.varHandle().set(segment, 0L, val)); MemoryLayout seq = MemoryLayout.sequenceLayout(10, layout); - assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).get(segment, 0L)); - assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).set(segment, 0L, val)); + assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).get(segment, 0L, 0L)); + assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).set(segment, 0L, 0L, val)); assertAligned(align, layout, () -> segment.spliterator(layout)); if (arr != null) { assertAligned(align, layout, () -> MemorySegment.copy(arr, 0, segment, layout, 0, 1)); diff --git a/test/jdk/java/foreign/TestIllegalLink.java b/test/jdk/java/foreign/TestIllegalLink.java index b898ad09a49..33bd8c5f6b5 100644 --- a/test/jdk/java/foreign/TestIllegalLink.java +++ b/test/jdk/java/foreign/TestIllegalLink.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @run testng/othervm --enable-native-access=ALL-UNNAMED TestIllegalLink */ @@ -47,6 +45,8 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import static java.lang.foreign.ValueLayout.*; + import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -102,7 +102,7 @@ public static Object[][] downcallOnlyOptions() { return new Object[][]{ { Linker.Option.firstVariadicArg(0) }, { Linker.Option.captureCallState("errno") }, - { Linker.Option.isTrivial() }, + { Linker.Option.critical() }, }; } @@ -128,7 +128,7 @@ public static Object[][] types() { { FunctionDescriptor.ofVoid(C_POINTER.withByteAlignment(2)), NO_OPTIONS, - IS_LE ? "Unsupported layout: 2%a8" : "Unsupported layout: 2%A8" + (IS_LE ? "Unsupported layout: 2%a" : "Unsupported layout: 2%A") + ADDRESS.byteSize() }, { FunctionDescriptor.ofVoid(ValueLayout.JAVA_CHAR.withByteAlignment(4)), @@ -156,7 +156,7 @@ public static Object[][] types() { }, { FunctionDescriptor.ofVoid(MemoryLayout.structLayout( - MemoryLayout.sequenceLayout( + MemoryLayout.sequenceLayout(1, C_INT.withByteAlignment(1) ))), NO_OPTIONS, @@ -181,17 +181,10 @@ public static Object[][] types() { IS_LE ? "Unsupported layout: I4" : "Unsupported layout: i4" }, { - FunctionDescriptor.of(MemoryLayout.structLayout(MemoryLayout.sequenceLayout(C_INT.withOrder(nonNativeOrder())))), + FunctionDescriptor.of(MemoryLayout.structLayout(MemoryLayout.sequenceLayout(1, C_INT.withOrder(nonNativeOrder())))), NO_OPTIONS, IS_LE ? "Unsupported layout: I4" : "Unsupported layout: i4" }, - { - FunctionDescriptor.ofVoid(MemoryLayout.structLayout( - ValueLayout.JAVA_LONG, - ValueLayout.JAVA_INT)), // missing trailing padding - NO_OPTIONS, - "has unexpected size" - }, { FunctionDescriptor.ofVoid(MemoryLayout.structLayout( ValueLayout.JAVA_INT, @@ -199,6 +192,11 @@ public static Object[][] types() { NO_OPTIONS, "has unexpected size" }, + { + FunctionDescriptor.ofVoid(), + new Linker.Option[]{Linker.Option.critical(), Linker.Option.captureCallState("errno")}, + "Incompatible linker options: captureCallState, critical" + }, })); for (ValueLayout illegalLayout : List.of(C_CHAR, ValueLayout.JAVA_CHAR, C_BOOL, C_SHORT, C_FLOAT)) { @@ -212,13 +210,22 @@ public static Object[][] types() { if (IS_SYSV) { cases.add(new Object[] { FunctionDescriptor.ofVoid(MemoryLayout.structLayout( - MemoryLayout.sequenceLayout( + MemoryLayout.sequenceLayout(Long.MAX_VALUE / C_INT.byteSize(), C_INT ))), NO_OPTIONS, "GroupLayout is too large" }); } + if (ValueLayout.JAVA_LONG.byteAlignment() == 8) { + cases.add(new Object[]{ + FunctionDescriptor.ofVoid(MemoryLayout.structLayout( + ValueLayout.JAVA_LONG, + ValueLayout.JAVA_INT)), // missing trailing padding + NO_OPTIONS, + "has unexpected size" + }); + } return cases.toArray(Object[][]::new); } diff --git a/test/jdk/java/foreign/TestIntrinsics.java b/test/jdk/java/foreign/TestIntrinsics.java index 49052d5f7a1..96b563e863f 100644 --- a/test/jdk/java/foreign/TestIntrinsics.java +++ b/test/jdk/java/foreign/TestIntrinsics.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true * --enable-native-access=ALL-UNNAMED diff --git a/test/jdk/java/foreign/TestLargeSegmentCopy.java b/test/jdk/java/foreign/TestLargeSegmentCopy.java index dc80d966abc..c1508e592c3 100644 --- a/test/jdk/java/foreign/TestLargeSegmentCopy.java +++ b/test/jdk/java/foreign/TestLargeSegmentCopy.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @requires sun.arch.data.model == "64" * @bug 8292851 * @run testng/othervm -Xmx4G TestLargeSegmentCopy diff --git a/test/jdk/java/foreign/TestLayoutPaths.java b/test/jdk/java/foreign/TestLayoutPaths.java index ceac0b2ce02..f9d254a5983 100644 --- a/test/jdk/java/foreign/TestLayoutPaths.java +++ b/test/jdk/java/foreign/TestLayoutPaths.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @run testng TestLayoutPaths */ @@ -42,6 +41,7 @@ import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.MemoryLayout.PathElement.sequenceElement; import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; import static java.lang.foreign.ValueLayout.JAVA_SHORT; import static org.testng.Assert.*; @@ -151,13 +151,13 @@ public void testBadAlignmentOfRoot() throws Throwable { VarHandle vhX = struct.varHandle(groupElement("x")); IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> { - vhX.set(seg, (short) 42); + vhX.set(seg, 0L, (short) 42); }); assertEquals(iae.getMessage(), expectedMessage); MethodHandle sliceX = struct.sliceHandle(groupElement("x")); iae = expectThrows(IllegalArgumentException.class, () -> { - MemorySegment slice = (MemorySegment) sliceX.invokeExact(seg); + MemorySegment slice = (MemorySegment) sliceX.invokeExact(seg, 0L); }); assertEquals(iae.getMessage(), expectedMessage); } @@ -271,7 +271,7 @@ public void testOffsetHandle(MemoryLayout layout, PathElement[] pathElements, lo long expectedByteOffset) throws Throwable { MethodHandle byteOffsetHandle = layout.byteOffsetHandle(pathElements); byteOffsetHandle = byteOffsetHandle.asSpreader(long[].class, indexes.length); - long actualByteOffset = (long) byteOffsetHandle.invokeExact(indexes); + long actualByteOffset = (long) byteOffsetHandle.invokeExact(0L, indexes); assertEquals(actualByteOffset, expectedByteOffset); } @@ -360,7 +360,7 @@ public void testSliceHandle(MemoryLayout layout, PathElement[] pathElements, lon try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(layout); - MemorySegment slice = (MemorySegment) sliceHandle.invokeExact(segment, indexes); + MemorySegment slice = (MemorySegment) sliceHandle.invokeExact(segment, 0L, indexes); assertEquals(slice.address() - segment.address(), expectedByteOffset); assertEquals(slice.byteSize(), selected.byteSize()); } diff --git a/test/jdk/java/foreign/TestLayouts.java b/test/jdk/java/foreign/TestLayouts.java index 0cabcdac553..ee758cf884d 100644 --- a/test/jdk/java/foreign/TestLayouts.java +++ b/test/jdk/java/foreign/TestLayouts.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng TestLayouts */ @@ -98,13 +97,13 @@ public void testIndexedSequencePath() { VarHandle indexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement()); // init segment for (int i = 0 ; i < 10 ; i++) { - indexHandle.set(segment, (long)i, i); + indexHandle.set(segment, 0L, (long)i, i); } //check statically indexed handles for (int i = 0 ; i < 10 ; i++) { VarHandle preindexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement(i)); - int expected = (int)indexHandle.get(segment, (long)i); - int found = (int)preindexHandle.get(segment); + int expected = (int)indexHandle.get(segment, 0L, (long)i); + int found = (int)preindexHandle.get(segment, 0L); assertEquals(expected, found); } } @@ -201,12 +200,7 @@ public void testSequenceBadCount() { () -> MemoryLayout.sequenceLayout(-2, JAVA_SHORT)); } - @Test(dataProvider = "basicLayouts") - public void testSequenceInferredCount(MemoryLayout layout) { - assertEquals(MemoryLayout.sequenceLayout(layout), - MemoryLayout.sequenceLayout(Long.MAX_VALUE / layout.byteSize(), layout)); - } - + @Test public void testSequenceNegativeElementCount() { assertThrows(IllegalArgumentException.class, // negative () -> MemoryLayout.sequenceLayout(-1, JAVA_SHORT)); @@ -300,14 +294,14 @@ public void testBadByteAlignment(MemoryLayout layout, long byteAlign) { @Test(dataProvider="layoutsAndAlignments", expectedExceptions = IllegalArgumentException.class) public void testBadSequenceElementAlignmentTooBig(MemoryLayout layout, long byteAlign) { layout = layout.withByteAlignment(layout.byteSize() * 2); // hyper-align - MemoryLayout.sequenceLayout(layout); + MemoryLayout.sequenceLayout(1, layout); } @Test(dataProvider="layoutsAndAlignments") public void testBadSequenceElementSizeNotMultipleOfAlignment(MemoryLayout layout, long byteAlign) { boolean shouldFail = layout.byteSize() % layout.byteAlignment() != 0; try { - MemoryLayout.sequenceLayout(layout); + MemoryLayout.sequenceLayout(1, layout); assertFalse(shouldFail); } catch (IllegalArgumentException ex) { assertTrue(shouldFail); @@ -338,14 +332,6 @@ public void testBadElementsElementSizeNotMultipleOfAlignment(MemoryLayout layout } } - @Test(dataProvider="layoutsAndAlignments") - public void testArrayElementVarHandleBadAlignment(MemoryLayout layout, long byteAlign) { - if (layout instanceof ValueLayout) { - assertThrows(UnsupportedOperationException.class, () -> - ((ValueLayout) layout).withByteAlignment(byteAlign * 2).arrayElementVarHandle()); - } - } - @Test(dataProvider="layoutsAndAlignments", expectedExceptions = IllegalArgumentException.class) public void testBadStruct(MemoryLayout layout, long byteAlign) { layout = layout.withByteAlignment(layout.byteSize() * 2); // hyper-align @@ -359,6 +345,37 @@ public void testSequenceElement() { PathElement.sequenceElement(3, 0); } + @Test + public void testVarHandleCaching() { + assertSame(JAVA_INT.varHandle(), JAVA_INT.varHandle()); + assertSame(JAVA_INT.withName("foo").varHandle(), JAVA_INT.varHandle()); + + assertNotSame(JAVA_INT_UNALIGNED.varHandle(), JAVA_INT.varHandle()); + assertNotSame(ADDRESS.withTargetLayout(JAVA_INT).varHandle(), ADDRESS.varHandle()); + } + + @Test(expectedExceptions=IllegalArgumentException.class, + expectedExceptionsMessageRegExp=".*Negative offset.*") + public void testScaleNegativeOffset() { + JAVA_INT.scale(-1, 0); + } + + @Test(expectedExceptions=IllegalArgumentException.class, + expectedExceptionsMessageRegExp=".*Negative index.*") + public void testScaleNegativeIndex() { + JAVA_INT.scale(0, -1); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void testScaleAddOverflow() { + JAVA_INT.scale(Long.MAX_VALUE, 1); + } + + @Test(expectedExceptions=ArithmeticException.class) + public void testScaleMultiplyOverflow() { + JAVA_INT.scale(0, Long.MAX_VALUE); + } + @DataProvider(name = "badAlignments") public Object[][] layoutsAndBadAlignments() { LayoutKind[] layoutKinds = LayoutKind.values(); @@ -496,7 +513,6 @@ public Object[][] validCarriers() { static Stream groupLayoutStream() { return Stream.of( MemoryLayout.sequenceLayout(10, JAVA_INT), - MemoryLayout.sequenceLayout(JAVA_INT), MemoryLayout.structLayout(JAVA_INT, MemoryLayout.paddingLayout(4), JAVA_LONG), MemoryLayout.unionLayout(JAVA_LONG, JAVA_DOUBLE) ); diff --git a/test/jdk/java/foreign/TestLinker.java b/test/jdk/java/foreign/TestLinker.java index 683dbbc6e28..42a373d5426 100644 --- a/test/jdk/java/foreign/TestLinker.java +++ b/test/jdk/java/foreign/TestLinker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @run testng TestLinker * @run testng/othervm/policy=security.policy @@ -37,6 +35,8 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.util.ArrayList; import java.util.Arrays; @@ -45,8 +45,10 @@ import static java.lang.foreign.MemoryLayout.*; import static java.lang.foreign.ValueLayout.JAVA_CHAR; import static java.lang.foreign.ValueLayout.JAVA_SHORT; +import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertNotSame; +import static org.testng.Assert.assertTrue; public class TestLinker extends NativeTestHelper { @@ -91,10 +93,6 @@ public static Object[][] namedDescriptors() { FunctionDescriptor.ofVoid(structLayout(C_INT).withName("x")) }, { FunctionDescriptor.ofVoid(structLayout(C_INT)), FunctionDescriptor.ofVoid(structLayout(C_INT.withName("x"))) }, - { FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)), - FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG.withName("x"))) }, - { FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)), - FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4).withName("x"), C_LONG_LONG)) }, { FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT))), FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT).withName("x"))) }, { FunctionDescriptor.ofVoid(structLayout(sequenceLayout(1, C_INT))), @@ -113,6 +111,12 @@ public static Object[][] namedDescriptors() { cases.add(new Object[]{ FunctionDescriptor.ofVoid(unionLayout(C_INT)), FunctionDescriptor.ofVoid(unionLayout(C_INT.withName("x"))) }); } + if (C_LONG_LONG.byteAlignment() == 8) { + cases.add(new Object[]{ FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)), + FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG.withName("x"))) }); + cases.add(new Object[]{ FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4), C_LONG_LONG)), + FunctionDescriptor.ofVoid(structLayout(C_INT, paddingLayout(4).withName("x"), C_LONG_LONG)) }); + } return cases.toArray(Object[][]::new); } @@ -140,4 +144,32 @@ public void testInvalidPreservedValueName() { Linker.Option.captureCallState("foo"); // throws } + @Test(dataProvider = "canonicalTypeNames") + public void testCanonicalLayouts(String typeName) { + MemoryLayout layout = LINKER.canonicalLayouts().get(typeName); + assertNotNull(layout); + assertTrue(layout instanceof ValueLayout); + } + + @DataProvider + public static Object[][] canonicalTypeNames() { + return new Object[][]{ + { "bool" }, + { "char" }, + { "short" }, + { "int" }, + { "long" }, + { "long long" }, + { "float" }, + { "double" }, + { "void*" }, + { "size_t" }, + { "wchar_t" }, + }; + } + + @Test(expectedExceptions=UnsupportedOperationException.class) + public void testCanonicalLayoutsUnmodifiable() { + LINKER.canonicalLayouts().put("asdf", C_INT); + } } diff --git a/test/jdk/java/foreign/TestMatrix.java b/test/jdk/java/foreign/TestMatrix.java index 6620e0a81d7..70be29fd55b 100644 --- a/test/jdk/java/foreign/TestMatrix.java +++ b/test/jdk/java/foreign/TestMatrix.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -32,8 +32,6 @@ */ /* @test id=UpcallHighArity-FF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * @@ -45,8 +43,6 @@ */ /* @test id=UpcallHighArity-TF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * @@ -58,8 +54,6 @@ */ /* @test id=UpcallHighArity-FT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * @@ -71,8 +65,6 @@ */ /* @test id=UpcallHighArity-TT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * @@ -84,8 +76,6 @@ */ /* @test id=DowncallScope-F - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * @@ -96,8 +86,6 @@ */ /* @test id=DowncallScope-T - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * @@ -108,8 +96,6 @@ */ /* @test id=DowncallStack-F - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * @@ -120,8 +106,6 @@ */ /* @test id=DowncallStack-T - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestDowncallBase * @@ -132,8 +116,6 @@ */ /* @test id=UpcallScope-FF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -145,8 +127,6 @@ */ /* @test id=UpcallScope-TF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -158,8 +138,6 @@ */ /* @test id=UpcallScope-FT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -171,8 +149,6 @@ */ /* @test id=UpcallScope-TT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -184,8 +160,6 @@ */ /* @test id=UpcallAsync-FF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -197,8 +171,6 @@ */ /* @test id=UpcallAsync-TF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -210,8 +182,6 @@ */ /* @test id=UpcallAsync-FT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -223,8 +193,6 @@ */ /* @test id=UpcallAsync-TT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -236,8 +204,6 @@ */ /* @test id=UpcallStack-FF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -249,8 +215,6 @@ */ /* @test id=UpcallStack-TF - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -262,8 +226,6 @@ */ /* @test id=UpcallStack-FT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -275,8 +237,6 @@ */ /* @test id=UpcallStack-TT - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * @@ -289,8 +249,6 @@ /* * @test id=VarArgs - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper * diff --git a/test/jdk/java/foreign/TestMemoryAccess.java b/test/jdk/java/foreign/TestMemoryAccess.java index 2260e903d24..19f480aa4b2 100644 --- a/test/jdk/java/foreign/TestMemoryAccess.java +++ b/test/jdk/java/foreign/TestMemoryAccess.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestMemoryAccess @@ -66,12 +65,6 @@ public void testArrayAccess(Function viewFactory, testArrayAccessInternal(viewFactory, seq, seq.varHandle(PathElement.sequenceElement()), checker); } - @Test(dataProvider = "arrayElements") - public void testArrayAccessAlt(Function viewFactory, ValueLayout elemLayout, ArrayChecker checker) { - SequenceLayout seq = MemoryLayout.sequenceLayout(10, elemLayout.withName("elem")); - testArrayAccessInternal(viewFactory, seq, elemLayout.arrayElementVarHandle(), checker); - } - @Test(dataProvider = "arrayElements") public void testPaddedArrayAccessByName(Function viewFactory, MemoryLayout elemLayout, ArrayChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(10, MemoryLayout.structLayout(MemoryLayout.paddingLayout(elemLayout.byteSize()), elemLayout.withName("elem"))); @@ -158,13 +151,6 @@ public void testMatrixAccess(Function viewFactory, PathElement.sequenceElement(), PathElement.sequenceElement()), checker); } - @Test(dataProvider = "matrixElements") - public void testMatrixAccessAlt(Function viewFactory, ValueLayout elemLayout, MatrixChecker checker) { - SequenceLayout seq = MemoryLayout.sequenceLayout(20, - MemoryLayout.sequenceLayout(10, elemLayout.withName("elem"))); - testMatrixAccessInternal(viewFactory, seq, elemLayout.arrayElementVarHandle(10), checker); - } - @Test(dataProvider = "matrixElements") public void testPaddedMatrixAccessByName(Function viewFactory, MemoryLayout elemLayout, MatrixChecker checker) { SequenceLayout seq = MemoryLayout.sequenceLayout(20, @@ -267,38 +253,38 @@ interface Checker { void check(VarHandle handle, MemorySegment segment); Checker BYTE = (handle, segment) -> { - handle.set(segment, (byte)42); - assertEquals(42, (byte)handle.get(segment)); + handle.set(segment, 0L, (byte)42); + assertEquals(42, (byte)handle.get(segment, 0L)); }; Checker SHORT = (handle, segment) -> { - handle.set(segment, (short)42); - assertEquals(42, (short)handle.get(segment)); + handle.set(segment, 0L, (short)42); + assertEquals(42, (short)handle.get(segment, 0L)); }; Checker CHAR = (handle, segment) -> { - handle.set(segment, (char)42); - assertEquals(42, (char)handle.get(segment)); + handle.set(segment, 0L, (char)42); + assertEquals(42, (char)handle.get(segment, 0L)); }; Checker INT = (handle, segment) -> { - handle.set(segment, 42); - assertEquals(42, (int)handle.get(segment)); + handle.set(segment, 0L, 42); + assertEquals(42, (int)handle.get(segment, 0L)); }; Checker LONG = (handle, segment) -> { - handle.set(segment, (long)42); - assertEquals(42, (long)handle.get(segment)); + handle.set(segment, 0L, (long)42); + assertEquals(42, (long)handle.get(segment, 0L)); }; Checker FLOAT = (handle, segment) -> { - handle.set(segment, (float)42); - assertEquals((float)42, (float)handle.get(segment)); + handle.set(segment, 0L, (float)42); + assertEquals((float)42, (float)handle.get(segment, 0L)); }; Checker DOUBLE = (handle, segment) -> { - handle.set(segment, (double)42); - assertEquals((double)42, (double)handle.get(segment)); + handle.set(segment, 0L, (double)42); + assertEquals((double)42, (double)handle.get(segment, 0L)); }; } @@ -344,38 +330,38 @@ interface ArrayChecker { void check(VarHandle handle, MemorySegment segment, long index); ArrayChecker BYTE = (handle, segment, i) -> { - handle.set(segment, i, (byte)i); - assertEquals(i, (byte)handle.get(segment, i)); + handle.set(segment, 0L, i, (byte)i); + assertEquals(i, (byte)handle.get(segment, 0L, i)); }; ArrayChecker SHORT = (handle, segment, i) -> { - handle.set(segment, i, (short)i); - assertEquals(i, (short)handle.get(segment, i)); + handle.set(segment, 0L, i, (short)i); + assertEquals(i, (short)handle.get(segment, 0L, i)); }; ArrayChecker CHAR = (handle, segment, i) -> { - handle.set(segment, i, (char)i); - assertEquals(i, (char)handle.get(segment, i)); + handle.set(segment, 0L, i, (char)i); + assertEquals(i, (char)handle.get(segment, 0L, i)); }; ArrayChecker INT = (handle, segment, i) -> { - handle.set(segment, i, (int)i); - assertEquals(i, (int)handle.get(segment, i)); + handle.set(segment, 0L, i, (int)i); + assertEquals(i, (int)handle.get(segment, 0L, i)); }; ArrayChecker LONG = (handle, segment, i) -> { - handle.set(segment, i, (long)i); - assertEquals(i, (long)handle.get(segment, i)); + handle.set(segment, 0L, i, (long)i); + assertEquals(i, (long)handle.get(segment, 0L, i)); }; ArrayChecker FLOAT = (handle, segment, i) -> { - handle.set(segment, i, (float)i); - assertEquals((float)i, (float)handle.get(segment, i)); + handle.set(segment, 0L, i, (float)i); + assertEquals((float)i, (float)handle.get(segment, 0L, i)); }; ArrayChecker DOUBLE = (handle, segment, i) -> { - handle.set(segment, i, (double)i); - assertEquals((double)i, (double)handle.get(segment, i)); + handle.set(segment, 0L, i, (double)i); + assertEquals((double)i, (double)handle.get(segment, 0L, i)); }; } @@ -429,48 +415,48 @@ interface MatrixChecker { void check(VarHandle handle, MemorySegment segment, long row, long col); MatrixChecker BYTE = (handle, segment, r, c) -> { - handle.set(segment, r, c, (byte)(r + c)); - assertEquals(r + c, (byte)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, (byte)(r + c)); + assertEquals(r + c, (byte)handle.get(segment, 0L, r, c)); }; MatrixChecker BOOLEAN = (handle, segment, r, c) -> { - handle.set(segment, r, c, (r + c) != 0); - assertEquals((r + c) != 0, (boolean)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, (r + c) != 0); + assertEquals((r + c) != 0, (boolean)handle.get(segment, 0L, r, c)); }; MatrixChecker SHORT = (handle, segment, r, c) -> { - handle.set(segment, r, c, (short)(r + c)); - assertEquals(r + c, (short)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, (short)(r + c)); + assertEquals(r + c, (short)handle.get(segment, 0L, r, c)); }; MatrixChecker CHAR = (handle, segment, r, c) -> { - handle.set(segment, r, c, (char)(r + c)); - assertEquals(r + c, (char)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, (char)(r + c)); + assertEquals(r + c, (char)handle.get(segment, 0L, r, c)); }; MatrixChecker INT = (handle, segment, r, c) -> { - handle.set(segment, r, c, (int)(r + c)); - assertEquals(r + c, (int)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, (int)(r + c)); + assertEquals(r + c, (int)handle.get(segment, 0L, r, c)); }; MatrixChecker LONG = (handle, segment, r, c) -> { - handle.set(segment, r, c, r + c); - assertEquals(r + c, (long)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, r + c); + assertEquals(r + c, (long)handle.get(segment, 0L, r, c)); }; MatrixChecker ADDR = (handle, segment, r, c) -> { - handle.set(segment, r, c, MemorySegment.ofAddress(r + c)); - assertEquals(MemorySegment.ofAddress(r + c), (MemorySegment) handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, MemorySegment.ofAddress(r + c)); + assertEquals(MemorySegment.ofAddress(r + c), (MemorySegment) handle.get(segment, 0L, r, c)); }; MatrixChecker FLOAT = (handle, segment, r, c) -> { - handle.set(segment, r, c, (float)(r + c)); - assertEquals((float)(r + c), (float)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, (float)(r + c)); + assertEquals((float)(r + c), (float)handle.get(segment, 0L, r, c)); }; MatrixChecker DOUBLE = (handle, segment, r, c) -> { - handle.set(segment, r, c, (double)(r + c)); - assertEquals((double)(r + c), (double)handle.get(segment, r, c)); + handle.set(segment, 0L, r, c, (double)(r + c)); + assertEquals((double)(r + c), (double)handle.get(segment, 0L, r, c)); }; } } diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java index f549a6117f6..fbcdc5f89b5 100644 --- a/test/jdk/java/foreign/TestMemoryAccessInstance.java +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng/othervm --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance */ diff --git a/test/jdk/java/foreign/TestMemoryAlignment.java b/test/jdk/java/foreign/TestMemoryAlignment.java index b6001284750..4d59ba9e4d7 100644 --- a/test/jdk/java/foreign/TestMemoryAlignment.java +++ b/test/jdk/java/foreign/TestMemoryAlignment.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng TestMemoryAlignment */ @@ -48,8 +47,8 @@ public void testAlignedAccess(long align) { VarHandle vh = aligned.varHandle(); try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(aligned);; - vh.set(segment, -42); - int val = (int)vh.get(segment); + vh.set(segment, 0L, -42); + int val = (int)vh.get(segment, 0L); assertEquals(val, -42); } } @@ -65,7 +64,7 @@ public void testUnalignedAccess(long align) { assertEquals(alignedGroup.byteAlignment(), align); VarHandle vh = aligned.varHandle(); MemorySegment segment = arena.allocate(alignedGroup);; - vh.set(segment.asSlice(1L), -42); + vh.set(segment.asSlice(1L), 0L, -42); assertEquals(align, 8); //this is the only case where access is aligned } catch (IllegalArgumentException ex) { assertNotEquals(align, 8); //if align != 8, access is always unaligned @@ -93,7 +92,7 @@ public void testUnalignedSequence(long align) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(layout);; for (long i = 0 ; i < 5 ; i++) { - vh.set(segment, i, -42); + vh.set(segment, 0L, i, -42); } } } catch (IllegalArgumentException ex) { @@ -116,12 +115,12 @@ public void testPackedAccess() { VarHandle vh_i = g.varHandle(PathElement.groupElement("c")); try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(g);; - vh_c.set(segment, Byte.MIN_VALUE); - assertEquals(vh_c.get(segment), Byte.MIN_VALUE); - vh_s.set(segment, Short.MIN_VALUE); - assertEquals(vh_s.get(segment), Short.MIN_VALUE); - vh_i.set(segment, Integer.MIN_VALUE); - assertEquals(vh_i.get(segment), Integer.MIN_VALUE); + vh_c.set(segment, 0L, Byte.MIN_VALUE); + assertEquals(vh_c.get(segment, 0L), Byte.MIN_VALUE); + vh_s.set(segment, 0L, Short.MIN_VALUE); + assertEquals(vh_s.get(segment, 0L), Short.MIN_VALUE); + vh_i.set(segment, 0L, Integer.MIN_VALUE); + assertEquals(vh_i.get(segment, 0L), Integer.MIN_VALUE); } } diff --git a/test/jdk/java/foreign/TestMemoryDereference.java b/test/jdk/java/foreign/TestMemoryDereference.java index 08172b87a4f..4680b148b65 100644 --- a/test/jdk/java/foreign/TestMemoryDereference.java +++ b/test/jdk/java/foreign/TestMemoryDereference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng TestMemoryDereference */ diff --git a/test/jdk/java/foreign/TestMemorySession.java b/test/jdk/java/foreign/TestMemorySession.java index e55ad572b46..617951f6b6b 100644 --- a/test/jdk/java/foreign/TestMemorySession.java +++ b/test/jdk/java/foreign/TestMemorySession.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules java.base/jdk.internal.foreign * @run testng/othervm TestMemorySession */ diff --git a/test/jdk/java/foreign/TestMismatch.java b/test/jdk/java/foreign/TestMismatch.java index e239a7c77e4..899bff09834 100644 --- a/test/jdk/java/foreign/TestMismatch.java +++ b/test/jdk/java/foreign/TestMismatch.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng TestMismatch */ diff --git a/test/jdk/java/foreign/TestNULLAddress.java b/test/jdk/java/foreign/TestNULLAddress.java index 170ec8ba351..c32b927b663 100644 --- a/test/jdk/java/foreign/TestNULLAddress.java +++ b/test/jdk/java/foreign/TestNULLAddress.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm * --enable-native-access=ALL-UNNAMED * TestNULLAddress diff --git a/test/jdk/java/foreign/TestNative.java b/test/jdk/java/foreign/TestNative.java index 032f5c1d807..b01e6005e9c 100644 --- a/test/jdk/java/foreign/TestNative.java +++ b/test/jdk/java/foreign/TestNative.java @@ -24,8 +24,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestNative */ @@ -208,34 +206,34 @@ public void testBadResize() { @DataProvider(name = "nativeAccessOps") public Object[][] nativeAccessOps() { Consumer byteInitializer = - (base) -> initBytes(base, bytes, (addr, pos) -> byteHandle.set(addr, pos, (byte)(long)pos)); + (base) -> initBytes(base, bytes, (addr, pos) -> byteHandle.set(addr, 0L, pos, (byte)(long)pos)); Consumer charInitializer = - (base) -> initBytes(base, chars, (addr, pos) -> charHandle.set(addr, pos, (char)(long)pos)); + (base) -> initBytes(base, chars, (addr, pos) -> charHandle.set(addr, 0L, pos, (char)(long)pos)); Consumer shortInitializer = - (base) -> initBytes(base, shorts, (addr, pos) -> shortHandle.set(addr, pos, (short)(long)pos)); + (base) -> initBytes(base, shorts, (addr, pos) -> shortHandle.set(addr, 0L, pos, (short)(long)pos)); Consumer intInitializer = - (base) -> initBytes(base, ints, (addr, pos) -> intHandle.set(addr, pos, (int)(long)pos)); + (base) -> initBytes(base, ints, (addr, pos) -> intHandle.set(addr, 0L, pos, (int)(long)pos)); Consumer floatInitializer = - (base) -> initBytes(base, floats, (addr, pos) -> floatHandle.set(addr, pos, (float)(long)pos)); + (base) -> initBytes(base, floats, (addr, pos) -> floatHandle.set(addr, 0L, pos, (float)(long)pos)); Consumer longInitializer = - (base) -> initBytes(base, longs, (addr, pos) -> longHandle.set(addr, pos, (long)pos)); + (base) -> initBytes(base, longs, (addr, pos) -> longHandle.set(addr, 0L, pos, (long)pos)); Consumer doubleInitializer = - (base) -> initBytes(base, doubles, (addr, pos) -> doubleHandle.set(addr, pos, (double)(long)pos)); + (base) -> initBytes(base, doubles, (addr, pos) -> doubleHandle.set(addr, 0L, pos, (double)(long)pos)); Consumer byteChecker = - (base) -> checkBytes(base, bytes, byteHandle::get, bb -> bb, TestNative::getByteBuffer, TestNative::getByteRaw); + (base) -> checkBytes(base, bytes, (addr, pos) -> byteHandle.get(addr, 0L, pos), bb -> bb, TestNative::getByteBuffer, TestNative::getByteRaw); Consumer charChecker = - (base) -> checkBytes(base, chars, charHandle::get, ByteBuffer::asCharBuffer, TestNative::getCharBuffer, TestNative::getCharRaw); + (base) -> checkBytes(base, chars, (addr, pos) -> charHandle.get(addr, 0L, pos), ByteBuffer::asCharBuffer, TestNative::getCharBuffer, TestNative::getCharRaw); Consumer shortChecker = - (base) -> checkBytes(base, shorts, shortHandle::get, ByteBuffer::asShortBuffer, TestNative::getShortBuffer, TestNative::getShortRaw); + (base) -> checkBytes(base, shorts, (addr, pos) -> shortHandle.get(addr, 0L, pos), ByteBuffer::asShortBuffer, TestNative::getShortBuffer, TestNative::getShortRaw); Consumer intChecker = - (base) -> checkBytes(base, ints, intHandle::get, ByteBuffer::asIntBuffer, TestNative::getIntBuffer, TestNative::getIntRaw); + (base) -> checkBytes(base, ints, (addr, pos) -> intHandle.get(addr, 0L, pos), ByteBuffer::asIntBuffer, TestNative::getIntBuffer, TestNative::getIntRaw); Consumer floatChecker = - (base) -> checkBytes(base, floats, floatHandle::get, ByteBuffer::asFloatBuffer, TestNative::getFloatBuffer, TestNative::getFloatRaw); + (base) -> checkBytes(base, floats, (addr, pos) -> floatHandle.get(addr, 0L, pos), ByteBuffer::asFloatBuffer, TestNative::getFloatBuffer, TestNative::getFloatRaw); Consumer longChecker = - (base) -> checkBytes(base, longs, longHandle::get, ByteBuffer::asLongBuffer, TestNative::getLongBuffer, TestNative::getLongRaw); + (base) -> checkBytes(base, longs, (addr, pos) -> longHandle.get(addr, 0L, pos), ByteBuffer::asLongBuffer, TestNative::getLongBuffer, TestNative::getLongRaw); Consumer doubleChecker = - (base) -> checkBytes(base, doubles, doubleHandle::get, ByteBuffer::asDoubleBuffer, TestNative::getDoubleBuffer, TestNative::getDoubleRaw); + (base) -> checkBytes(base, doubles, (addr, pos) -> doubleHandle.get(addr, 0L, pos), ByteBuffer::asDoubleBuffer, TestNative::getDoubleBuffer, TestNative::getDoubleRaw); return new Object[][]{ {byteChecker, byteInitializer, bytes}, diff --git a/test/jdk/java/foreign/TestNulls.java b/test/jdk/java/foreign/TestNulls.java index 0e1d13c1586..6822863c2ca 100644 --- a/test/jdk/java/foreign/TestNulls.java +++ b/test/jdk/java/foreign/TestNulls.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.ref * @run testng/othervm * --enable-native-access=ALL-UNNAMED @@ -144,7 +142,7 @@ static void addDefaultMapping(Class carrier, Z value) { addDefaultMapping(Class.class, String.class); addDefaultMapping(Runnable.class, () -> {}); addDefaultMapping(Object.class, new Object()); - addDefaultMapping(VarHandle.class, MethodHandles.memorySegmentViewVarHandle(JAVA_INT)); + addDefaultMapping(VarHandle.class, JAVA_INT.varHandle()); addDefaultMapping(MethodHandle.class, MethodHandles.identity(int.class)); addDefaultMapping(List.class, List.of()); addDefaultMapping(Charset.class, Charset.defaultCharset()); diff --git a/test/jdk/java/foreign/TestOfBufferIssue.java b/test/jdk/java/foreign/TestOfBufferIssue.java index df8d62ccf20..c30384efc69 100644 --- a/test/jdk/java/foreign/TestOfBufferIssue.java +++ b/test/jdk/java/foreign/TestOfBufferIssue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -33,7 +33,6 @@ * @test * @bug 8294621 * @summary test that StringCharBuffer is not accepted by MemorySegment::ofBuffer - * @enablePreview * @run testng TestOfBufferIssue */ diff --git a/test/jdk/java/foreign/TestReshape.java b/test/jdk/java/foreign/TestReshape.java index 4cba4a53e54..5b64a3d38b6 100644 --- a/test/jdk/java/foreign/TestReshape.java +++ b/test/jdk/java/foreign/TestReshape.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng TestReshape */ diff --git a/test/jdk/java/foreign/TestRestricted.java b/test/jdk/java/foreign/TestRestricted.java index 30112e0aaea..beccd895829 100644 --- a/test/jdk/java/foreign/TestRestricted.java +++ b/test/jdk/java/foreign/TestRestricted.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules java.base/jdk.internal.javac * @modules java.base/jdk.internal.reflect * @run testng TestRestricted diff --git a/test/jdk/java/foreign/TestScopedOperations.java b/test/jdk/java/foreign/TestScopedOperations.java index bef037ff2c0..70223c00c00 100644 --- a/test/jdk/java/foreign/TestScopedOperations.java +++ b/test/jdk/java/foreign/TestScopedOperations.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestScopedOperations */ @@ -122,21 +120,21 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO ScopedOperation.ofScope(a -> a.allocate(1), "Arena::allocate/size"); ScopedOperation.ofScope(a -> a.allocate(1, 1), "Arena::allocate/size/align"); ScopedOperation.ofScope(a -> a.allocate(JAVA_BYTE), "Arena::allocate/layout"); - ScopedOperation.ofScope(a -> a.allocate(JAVA_BYTE, (byte) 0), "Arena::allocate/byte"); - ScopedOperation.ofScope(a -> a.allocate(ValueLayout.JAVA_CHAR, (char) 0), "Arena::allocate/char"); - ScopedOperation.ofScope(a -> a.allocate(ValueLayout.JAVA_SHORT, (short) 0), "Arena::allocate/short"); - ScopedOperation.ofScope(a -> a.allocate(ValueLayout.JAVA_INT, 0), "Arena::allocate/int"); - ScopedOperation.ofScope(a -> a.allocate(ValueLayout.JAVA_FLOAT, 0f), "Arena::allocate/float"); - ScopedOperation.ofScope(a -> a.allocate(ValueLayout.JAVA_LONG, 0L), "Arena::allocate/long"); - ScopedOperation.ofScope(a -> a.allocate(ValueLayout.JAVA_DOUBLE, 0d), "Arena::allocate/double"); - ScopedOperation.ofScope(a -> a.allocateArray(JAVA_BYTE, 1L), "Arena::allocateArray/size"); - ScopedOperation.ofScope(a -> a.allocateArray(JAVA_BYTE, new byte[]{0}), "Arena::allocateArray/byte"); - ScopedOperation.ofScope(a -> a.allocateArray(ValueLayout.JAVA_CHAR, new char[]{0}), "Arena::allocateArray/char"); - ScopedOperation.ofScope(a -> a.allocateArray(ValueLayout.JAVA_SHORT, new short[]{0}), "Arena::allocateArray/short"); - ScopedOperation.ofScope(a -> a.allocateArray(ValueLayout.JAVA_INT, new int[]{0}), "Arena::allocateArray/int"); - ScopedOperation.ofScope(a -> a.allocateArray(ValueLayout.JAVA_FLOAT, new float[]{0}), "Arena::allocateArray/float"); - ScopedOperation.ofScope(a -> a.allocateArray(ValueLayout.JAVA_LONG, new long[]{0}), "Arena::allocateArray/long"); - ScopedOperation.ofScope(a -> a.allocateArray(ValueLayout.JAVA_DOUBLE, new double[]{0}), "Arena::allocateArray/double"); + ScopedOperation.ofScope(a -> a.allocateFrom(JAVA_BYTE, (byte) 0), "Arena::allocate/byte"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_CHAR, (char) 0), "Arena::allocate/char"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_SHORT, (short) 0), "Arena::allocate/short"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_INT, 0), "Arena::allocate/int"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_FLOAT, 0f), "Arena::allocate/float"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_LONG, 0L), "Arena::allocate/long"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_DOUBLE, 0d), "Arena::allocate/double"); + ScopedOperation.ofScope(a -> a.allocate(JAVA_BYTE, 1L), "Arena::allocate/size"); + ScopedOperation.ofScope(a -> a.allocateFrom(JAVA_BYTE, new byte[]{0}), "Arena::allocateFrom/byte"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_CHAR, new char[]{0}), "Arena::allocateFrom/char"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_SHORT, new short[]{0}), "Arena::allocateFrom/short"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_INT, new int[]{0}), "Arena::allocateFrom/int"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_FLOAT, new float[]{0}), "Arena::allocateFrom/float"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_LONG, new long[]{0}), "Arena::allocateFrom/long"); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_DOUBLE, new double[]{0}), "Arena::allocateFrom/double"); }; @DataProvider(name = "scopedOperations") diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java index 4c574a60500..c137eb20371 100644 --- a/test/jdk/java/foreign/TestSegmentAllocators.java +++ b/test/jdk/java/foreign/TestSegmentAllocators.java @@ -24,14 +24,12 @@ /* * @test - * @enablePreview * @modules java.base/jdk.internal.foreign * @run testng/othervm TestSegmentAllocators */ import java.lang.foreign.*; -import jdk.internal.foreign.MappedMemorySegmentImpl; import jdk.internal.foreign.NativeMemorySegmentImpl; import org.testng.annotations.*; @@ -82,7 +80,7 @@ public void testAllocation(Z value, AllocationFactory assertEquals(address.byteSize(), alignedLayout.byteSize()); addressList.add(address); VarHandle handle = handleFactory.apply(alignedLayout); - assertEquals(value, handle.get(address)); + assertEquals(value, handle.get(address, 0L)); } boolean isBound = allocationFactory.isBound(); try { @@ -148,12 +146,12 @@ public void testBadAllocationAlignNotPowerTwo(SegmentAllocator allocator) { @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationArrayNegSize(SegmentAllocator allocator) { - allocator.allocateArray(ValueLayout.JAVA_BYTE, -1); + allocator.allocate(ValueLayout.JAVA_BYTE, -1); } @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationArrayOverflow(SegmentAllocator allocator) { - allocator.allocateArray(ValueLayout.JAVA_LONG, Long.MAX_VALUE); + allocator.allocate(ValueLayout.JAVA_LONG, Long.MAX_VALUE); } @Test(expectedExceptions = OutOfMemoryError.class) @@ -169,22 +167,22 @@ public void testArrayAllocateDelegation() { SegmentAllocator allocator = new SegmentAllocator() { @Override public MemorySegment allocate(long bytesSize, long byteAlignment) { - return null; + return MemorySegment.NULL; } @Override - public MemorySegment allocateArray(MemoryLayout elementLayout, long count) { + public MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source, ValueLayout sourceElementLayout, long sourceOffset, long elementCount) { calls.incrementAndGet(); - return null; - }; + return MemorySegment.NULL; + } }; - allocator.allocateArray(ValueLayout.JAVA_BYTE); - allocator.allocateArray(ValueLayout.JAVA_SHORT); - allocator.allocateArray(ValueLayout.JAVA_CHAR); - allocator.allocateArray(ValueLayout.JAVA_INT); - allocator.allocateArray(ValueLayout.JAVA_FLOAT); - allocator.allocateArray(ValueLayout.JAVA_LONG); - allocator.allocateArray(ValueLayout.JAVA_DOUBLE); + allocator.allocateFrom(ValueLayout.JAVA_BYTE); + allocator.allocateFrom(ValueLayout.JAVA_SHORT); + allocator.allocateFrom(ValueLayout.JAVA_CHAR); + allocator.allocateFrom(ValueLayout.JAVA_INT); + allocator.allocateFrom(ValueLayout.JAVA_FLOAT); + allocator.allocateFrom(ValueLayout.JAVA_LONG); + allocator.allocateFrom(ValueLayout.JAVA_DOUBLE); assertEquals(calls.get(), 7); } @@ -193,7 +191,6 @@ public void testStringAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); SegmentAllocator allocator = new SegmentAllocator() { @Override - public MemorySegment allocate(long byteSize, long byteAlignment) { return Arena.ofAuto().allocate(byteSize, byteAlignment); } @@ -204,7 +201,7 @@ public MemorySegment allocate(long size) { return allocate(size, 1); }; }; - allocator.allocateUtf8String("Hello"); + allocator.allocateFrom("Hello"); assertEquals(calls.get(), 1); } @@ -252,52 +249,52 @@ static Object[][] scalarAllocations() { List scalarAllocations = new ArrayList<>(); for (AllocationFactory factory : AllocationFactory.values()) { scalarAllocations.add(new Object[] { (byte)42, factory, ValueLayout.JAVA_BYTE, - (AllocationFunction.OfByte) SegmentAllocator::allocate, + (AllocationFunction.OfByte) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfShort) SegmentAllocator::allocate, + (AllocationFunction.OfShort) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfChar) SegmentAllocator::allocate, + (AllocationFunction.OfChar) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42, factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfInt) SegmentAllocator::allocate, + (AllocationFunction.OfInt) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfFloat) SegmentAllocator::allocate, + (AllocationFunction.OfFloat) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfLong) SegmentAllocator::allocate, + (AllocationFunction.OfLong) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfDouble) SegmentAllocator::allocate, + (AllocationFunction.OfDouble) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfAddress) SegmentAllocator::allocate, + (AllocationFunction.OfAddress) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfShort) SegmentAllocator::allocate, + (AllocationFunction.OfShort) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfChar) SegmentAllocator::allocate, + (AllocationFunction.OfChar) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42, factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfInt) SegmentAllocator::allocate, + (AllocationFunction.OfInt) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfFloat) SegmentAllocator::allocate, + (AllocationFunction.OfFloat) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfLong) SegmentAllocator::allocate, + (AllocationFunction.OfLong) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfDouble) SegmentAllocator::allocate, + (AllocationFunction.OfDouble) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfAddress) SegmentAllocator::allocate, + (AllocationFunction.OfAddress) SegmentAllocator::allocateFrom, (Function)l -> l.varHandle() }); } return scalarAllocations.toArray(Object[][]::new); @@ -308,46 +305,46 @@ static Object[][] arrayAllocations() { List arrayAllocations = new ArrayList<>(); for (AllocationFactory factory : AllocationFactory.values()) { arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_BYTE, - (AllocationFunction.OfByteArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfByteArray) SegmentAllocator::allocateFrom, ToArrayHelper.toByteArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfCharArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom, ToArrayHelper.toCharArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfShortArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom, ToArrayHelper.toShortArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfIntArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom, ToArrayHelper.toIntArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfFloatArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom, ToArrayHelper.toFloatArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfLongArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom, ToArrayHelper.toLongArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), - (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom, ToArrayHelper.toDoubleArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfCharArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom, ToArrayHelper.toCharArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfShortArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom, ToArrayHelper.toShortArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfIntArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom, ToArrayHelper.toIntArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfFloatArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom, ToArrayHelper.toFloatArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfLongArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom, ToArrayHelper.toLongArray }); arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), - (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateArray, + (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom, ToArrayHelper.toDoubleArray }); }; return arrayAllocations.toArray(Object[][]::new); diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java index cf118658271..85f843eddd7 100644 --- a/test/jdk/java/foreign/TestSegmentCopy.java +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @run testng TestSegmentCopy */ @@ -171,7 +170,7 @@ long size() { } VarHandle handle() { - return MethodHandles.memorySegmentViewVarHandle(layout); + return layout.varHandle(); } void set(MemorySegment segment, long offset, int index, int val) { diff --git a/test/jdk/java/foreign/TestSegmentOffset.java b/test/jdk/java/foreign/TestSegmentOffset.java index f5baa6bc82c..cf335e4ff88 100644 --- a/test/jdk/java/foreign/TestSegmentOffset.java +++ b/test/jdk/java/foreign/TestSegmentOffset.java @@ -23,13 +23,13 @@ /* * @test - * @enablePreview * @run testng TestSegmentOffset */ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; +import org.testng.SkipException; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -44,27 +44,21 @@ public class TestSegmentOffset { @Test(dataProvider = "slices") public void testOffset(SegmentSlice s1, SegmentSlice s2) { + if (s1.kind != s2.kind) { + throw new SkipException("Slices of different segment kinds"); + } if (s1.contains(s2)) { // check that a segment and its overlapping segment point to same elements - long offset = s1.segment.segmentOffset(s2.segment); + long offset = s1.offset(s2); for (int i = 0; i < s2.size(); i++) { out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i); byte expected = s2.segment.get(JAVA_BYTE, i); byte found = s1.segment.get(JAVA_BYTE, i + offset); assertEquals(found, expected); } - } else if (s1.kind != s2.kind) { - // check that offset from s1 to s2 fails - try { - long offset = s1.segment.segmentOffset(s2.segment); - out.format("testOffset s1:%s, s2:%s, offset:%d\n", s1, s2, offset); - fail("offset unexpectedly passed!"); - } catch (UnsupportedOperationException ex) { - assertTrue(ex.getMessage().contains("Cannot compute offset from native to heap (or vice versa).")); - } } else if (!s2.contains(s1)) { // disjoint segments - check that offset is out of bounds - long offset = s1.segment.segmentOffset(s2.segment); + long offset = s1.offset(s2); for (int i = 0; i < s2.size(); i++) { out.format("testOffset s1:%s, s2:%s, offset:%d, i:%s\n", s1, s2, offset, i); s2.segment.get(JAVA_BYTE, i); @@ -116,6 +110,10 @@ boolean contains(SegmentSlice other) { int size() { return last - first + 1; } + + long offset(SegmentSlice that) { + return that.segment.address() - segment.address(); + } } @DataProvider(name = "slices") diff --git a/test/jdk/java/foreign/TestSegmentOverlap.java b/test/jdk/java/foreign/TestSegmentOverlap.java index da327e3afed..817d79b08cc 100644 --- a/test/jdk/java/foreign/TestSegmentOverlap.java +++ b/test/jdk/java/foreign/TestSegmentOverlap.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng/othervm TestSegmentOverlap */ diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index f8f5a2b0896..91c23b02da5 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -23,8 +23,7 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" + * @requires vm.bits == 64 * @run testng/othervm -Xmx4G -XX:MaxDirectMemorySize=1M --enable-native-access=ALL-UNNAMED TestSegments */ @@ -84,7 +83,7 @@ public void testNativeAllocationTooBig() { @Test public void testNativeSegmentIsZeroed() { - VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); + VarHandle byteHandle = ValueLayout.JAVA_BYTE.varHandle(); try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(1000, 1); for (long i = 0 ; i < segment.byteSize() ; i++) { @@ -95,7 +94,7 @@ public void testNativeSegmentIsZeroed() { @Test public void testSlices() { - VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); + VarHandle byteHandle = ValueLayout.JAVA_BYTE.varHandle(); try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(10, 1); //init @@ -263,7 +262,7 @@ public Object[][] segmentFactories() { @Test(dataProvider = "segmentFactories") public void testFill(Supplier segmentSupplier) { - VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); + VarHandle byteHandle = ValueLayout.JAVA_BYTE.varHandle(); for (byte value : new byte[] {(byte) 0xFF, (byte) 0x00, (byte) 0x45}) { MemorySegment segment = segmentSupplier.get(); diff --git a/test/jdk/java/foreign/TestSharedAccess.java b/test/jdk/java/foreign/TestSharedAccess.java index 62f20c6be58..9823f6f0bbf 100644 --- a/test/jdk/java/foreign/TestSharedAccess.java +++ b/test/jdk/java/foreign/TestSharedAccess.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @run testng/othervm --enable-native-access=ALL-UNNAMED TestSharedAccess */ @@ -151,10 +150,10 @@ public void testOutsideConfinementThread() throws Throwable { } static int getInt(MemorySegment base) { - return (int)intHandle.getVolatile(base); + return (int)intHandle.getVolatile(base, 0L); } static void setInt(MemorySegment base, int value) { - intHandle.setVolatile(base, value); + intHandle.setVolatile(base, 0L, value); } } diff --git a/test/jdk/java/foreign/TestSlices.java b/test/jdk/java/foreign/TestSlices.java index fb8c6dc95dd..88fe98cc847 100644 --- a/test/jdk/java/foreign/TestSlices.java +++ b/test/jdk/java/foreign/TestSlices.java @@ -35,7 +35,6 @@ /* * @test - * @enablePreview * @run testng/othervm -Xverify:all TestSlices */ public class TestSlices { @@ -53,7 +52,7 @@ public void testSlices(VarHandle handle, int lo, int hi, int[] values) { //init for (long i = 0 ; i < 2 ; i++) { for (long j = 0 ; j < 5 ; j++) { - VH_ALL.set(segment, i, j, (int)j + 1 + ((int)i * 5)); + VH_ALL.set(segment, 0L, i, j, (int)j + 1 + ((int)i * 5)); } } @@ -65,8 +64,8 @@ public void testSlices(VarHandle handle, int lo, int hi, int[] values) { public void testSliceBadIndex(VarHandle handle, int lo, int hi, int[] values) { try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(LAYOUT);; - assertThrows(() -> handle.get(segment, lo, 0)); - assertThrows(() -> handle.get(segment, 0, hi)); + assertThrows(() -> handle.get(segment, 0L, lo, 0)); + assertThrows(() -> handle.get(segment, 0L, 0, hi)); } } @@ -74,7 +73,7 @@ static void checkSlice(MemorySegment segment, VarHandle handle, long i_max, long int index = 0; for (long i = 0 ; i < i_max ; i++) { for (long j = 0 ; j < j_max ; j++) { - int x = (int) handle.get(segment, i, j); + int x = (int) handle.get(segment, 0L, i, j); assertEquals(x, values[index++]); } } diff --git a/test/jdk/java/foreign/TestSpliterator.java b/test/jdk/java/foreign/TestSpliterator.java index 02df427cea2..f15e038879e 100644 --- a/test/jdk/java/foreign/TestSpliterator.java +++ b/test/jdk/java/foreign/TestSpliterator.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @run testng TestSpliterator */ @@ -44,8 +43,6 @@ public class TestSpliterator { - static final VarHandle INT_HANDLE = ValueLayout.JAVA_INT.arrayElementVarHandle(); - final static int CARRIER_SIZE = 4; @Test(dataProvider = "splits") @@ -56,7 +53,7 @@ public void testSum(int size, int threshold) { try (Arena arena = Arena.ofShared()) { MemorySegment segment = arena.allocate(layout);; for (int i = 0; i < layout.elementCount(); i++) { - INT_HANDLE.set(segment, (long) i, i); + segment.setAtIndex(ValueLayout.JAVA_INT, i, i); } long expected = LongStream.range(0, layout.elementCount()).sum(); //serial @@ -83,7 +80,7 @@ public void testSumSameThread() { Arena scope = Arena.ofAuto(); MemorySegment segment = scope.allocate(layout); for (int i = 0; i < layout.elementCount(); i++) { - INT_HANDLE.set(segment, (long) i, i); + segment.setAtIndex(ValueLayout.JAVA_INT, i, i); } long expected = LongStream.range(0, layout.elementCount()).sum(); @@ -160,14 +157,14 @@ public void testHyperAligned() { } static long sumSingle(long acc, MemorySegment segment) { - return acc + (int)INT_HANDLE.get(segment, 0L); + return acc + segment.getAtIndex(ValueLayout.JAVA_INT, 0); } static long sum(long start, MemorySegment segment) { long sum = start; int length = (int)segment.byteSize(); for (int i = 0 ; i < length / CARRIER_SIZE ; i++) { - sum += (int)INT_HANDLE.get(segment, (long)i); + sum += segment.getAtIndex(ValueLayout.JAVA_INT, i); } return sum; } diff --git a/test/jdk/java/foreign/TestStringEncoding.java b/test/jdk/java/foreign/TestStringEncoding.java index d90138b1a3d..d7d27cdc452 100644 --- a/test/jdk/java/foreign/TestStringEncoding.java +++ b/test/jdk/java/foreign/TestStringEncoding.java @@ -24,41 +24,71 @@ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import org.testng.annotations.*; import static org.testng.Assert.*; /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng TestStringEncoding */ public class TestStringEncoding { @Test(dataProvider = "strings") - public void testStrings(String testString, int expectedByteLength) { - try (Arena arena = Arena.ofConfined()) { - MemorySegment text = arena.allocateUtf8String(testString); + public void testStrings(String testString) throws ReflectiveOperationException { + for (Charset charset : Charset.availableCharsets().values()) { + if (isStandard(charset)) { + try (Arena arena = Arena.ofConfined()) { + MemorySegment text = arena.allocateFrom(testString, charset); - assertEquals(text.byteSize(), expectedByteLength); + int terminatorSize = "\0".getBytes(charset).length; + if (charset == StandardCharsets.UTF_16) { + terminatorSize -= 2; // drop BOM + } + // Note that the JDK's UTF_32 encoder doesn't add a BOM. + // This is legal under the Unicode standard, and means the byte order is BE. + // See: https://unicode.org/faq/utf_bom.html#gen7 - String roundTrip = text.getUtf8String(0); - assertEquals(roundTrip, testString); + int expectedByteLength = + testString.getBytes(charset).length + + terminatorSize; + + assertEquals(text.byteSize(), expectedByteLength); + + String roundTrip = text.getString(0, charset); + if (charset.newEncoder().canEncode(testString)) { + assertEquals(roundTrip, testString); + } + } + } else { + assertThrows(IllegalArgumentException.class, () -> Arena.global().allocateFrom(testString, charset)); + } } } @DataProvider public static Object[][] strings() { return new Object[][] { - { "testing", 8 }, - { "", 1 }, - { "X", 2 }, - { "12345", 6 }, - { "yen \u00A5", 7 }, // in UTF-8 2 bytes: 0xC2 0xA5 - { "snowman \u26C4", 12 }, // in UTF-8 three bytes: 0xE2 0x9B 0x84 - { "rainbow \uD83C\uDF08", 13 } // in UTF-8 four bytes: 0xF0 0x9F 0x8C 0x88 + { "testing" }, + { "" }, + { "X" }, + { "12345" }, + { "yen \u00A5" }, + { "snowman \u26C4" }, + { "rainbow \uD83C\uDF08" } }; } + + boolean isStandard(Charset charset) throws ReflectiveOperationException { + for (Field standardCharset : StandardCharsets.class.getDeclaredFields()) { + if (standardCharset.get(null) == charset) { + return true; + } + } + return false; + } } diff --git a/test/jdk/java/foreign/TestTypeAccess.java b/test/jdk/java/foreign/TestTypeAccess.java index 677c0d3abac..13d3eaf0c0f 100644 --- a/test/jdk/java/foreign/TestTypeAccess.java +++ b/test/jdk/java/foreign/TestTypeAccess.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @run testng TestTypeAccess */ @@ -43,7 +42,7 @@ public class TestTypeAccess { @Test(expectedExceptions=ClassCastException.class) public void testMemoryAddressCoordinateAsString() { - int v = (int)INT_HANDLE.get("string"); + int v = (int)INT_HANDLE.get("string", 0L); } @Test(expectedExceptions=WrongMethodTypeException.class) @@ -54,8 +53,8 @@ public void testMemoryCoordinatePrimitive() { @Test(expectedExceptions=ClassCastException.class) public void testMemoryAddressValueGetAsString() { try (Arena arena = Arena.ofConfined()) { - MemorySegment s = arena.allocate(8, 8);; - String address = (String)ADDR_HANDLE.get(s); + MemorySegment s = arena.allocate(8, 8); + String address = (String)ADDR_HANDLE.get(s, 0L); } } @@ -63,15 +62,15 @@ public void testMemoryAddressValueGetAsString() { public void testMemoryAddressValueSetAsString() { try (Arena arena = Arena.ofConfined()) { MemorySegment s = arena.allocate(8, 8);; - ADDR_HANDLE.set(s, "string"); + ADDR_HANDLE.set(s, 0L, "string"); } } @Test(expectedExceptions=WrongMethodTypeException.class) public void testMemoryAddressValueGetAsPrimitive() { try (Arena arena = Arena.ofConfined()) { - MemorySegment s = arena.allocate(8, 8);; - int address = (int)ADDR_HANDLE.get(s); + MemorySegment s = arena.allocate(8, 8); + int address = (int)ADDR_HANDLE.get(s, 0L); } } diff --git a/test/jdk/java/foreign/TestUnsupportedLinker.java b/test/jdk/java/foreign/TestUnsupportedLinker.java deleted file mode 100644 index 7ebd83a8a99..00000000000 --- a/test/jdk/java/foreign/TestUnsupportedLinker.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @enablePreview - * - * @run testng/othervm -Djdk.internal.foreign.CABI=UNSUPPORTED --enable-native-access=ALL-UNNAMED TestUnsupportedLinker - */ - -import java.lang.foreign.Linker; - -import org.testng.annotations.Test; - -public class TestUnsupportedLinker { - - @Test(expectedExceptions = UnsupportedOperationException.class) - public void testLinker() { - Linker.nativeLinker(); - } -} diff --git a/test/jdk/java/foreign/TestUpcallAsync.java b/test/jdk/java/foreign/TestUpcallAsync.java index e009701afc2..943a82a2931 100644 --- a/test/jdk/java/foreign/TestUpcallAsync.java +++ b/test/jdk/java/foreign/TestUpcallAsync.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires !vm.musl * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase diff --git a/test/jdk/java/foreign/TestUpcallException.java b/test/jdk/java/foreign/TestUpcallException.java index b9d7874501b..fa922b9fb39 100644 --- a/test/jdk/java/foreign/TestUpcallException.java +++ b/test/jdk/java/foreign/TestUpcallException.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @library /test/lib * @build TestUpcallException * diff --git a/test/jdk/java/foreign/TestUpcallHighArity.java b/test/jdk/java/foreign/TestUpcallHighArity.java index f5f76923bb9..7bb369c884d 100644 --- a/test/jdk/java/foreign/TestUpcallHighArity.java +++ b/test/jdk/java/foreign/TestUpcallHighArity.java @@ -24,8 +24,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallHighArity * @@ -48,15 +46,6 @@ public class TestUpcallHighArity extends CallGeneratorHelper { static final MethodHandle MH_do_upcall; - static final Linker LINKER = Linker.nativeLinker(); - - // struct S_PDI { void* p0; double p1; int p2; }; - static final MemoryLayout S_PDI_LAYOUT = MemoryLayout.structLayout( - C_POINTER.withName("p0"), - C_DOUBLE.withName("p1"), - C_INT.withName("p2"), - MemoryLayout.paddingLayout(4) - ); static { System.loadLibrary("TestUpcallHighArity"); diff --git a/test/jdk/java/foreign/TestUpcallScope.java b/test/jdk/java/foreign/TestUpcallScope.java index b00aa406c99..e16dbb3435b 100644 --- a/test/jdk/java/foreign/TestUpcallScope.java +++ b/test/jdk/java/foreign/TestUpcallScope.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase * diff --git a/test/jdk/java/foreign/TestUpcallStack.java b/test/jdk/java/foreign/TestUpcallStack.java index 99bb4647466..81241b3a156 100644 --- a/test/jdk/java/foreign/TestUpcallStack.java +++ b/test/jdk/java/foreign/TestUpcallStack.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign * @build NativeTestHelper CallGeneratorHelper TestUpcallBase diff --git a/test/jdk/java/foreign/TestUpcallStructScope.java b/test/jdk/java/foreign/TestUpcallStructScope.java index 72344c4438b..14809139dff 100644 --- a/test/jdk/java/foreign/TestUpcallStructScope.java +++ b/test/jdk/java/foreign/TestUpcallStructScope.java @@ -24,8 +24,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * * @run testng/othervm/native * --enable-native-access=ALL-UNNAMED @@ -51,17 +49,8 @@ public class TestUpcallStructScope extends NativeTestHelper { static final MethodHandle MH_do_upcall; - static final Linker LINKER = Linker.nativeLinker(); static final MethodHandle MH_Consumer_accept; - // struct S_PDI { void* p0; double p1; int p2; }; - static final MemoryLayout S_PDI_LAYOUT = MemoryLayout.structLayout( - C_POINTER.withName("p0"), - C_DOUBLE.withName("p1"), - C_INT.withName("p2"), - MemoryLayout.paddingLayout(4) - ); - static { System.loadLibrary("TestUpcallStructScope"); MH_do_upcall = LINKER.downcallHandle( diff --git a/test/jdk/java/foreign/TestValueLayouts.java b/test/jdk/java/foreign/TestValueLayouts.java index 97d6273297d..ec44ad60aca 100644 --- a/test/jdk/java/foreign/TestValueLayouts.java +++ b/test/jdk/java/foreign/TestValueLayouts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules java.base/jdk.internal.misc * @run testng TestValueLayouts */ diff --git a/test/jdk/java/foreign/TestVarArgs.java b/test/jdk/java/foreign/TestVarArgs.java index 8f1ef4e862b..d52253bfe87 100644 --- a/test/jdk/java/foreign/TestVarArgs.java +++ b/test/jdk/java/foreign/TestVarArgs.java @@ -24,8 +24,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @run testng/othervm --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 TestVarArgs */ @@ -40,6 +38,7 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -51,7 +50,6 @@ public class TestVarArgs extends CallGeneratorHelper { - static final VarHandle VH_IntArray = C_INT.arrayElementVarHandle(); static final MethodHandle MH_CHECK; static final Linker LINKER = Linker.nativeLinker(); @@ -82,7 +80,7 @@ public void testVarArgs(int count, String fName, Ret ret, // ignore this stuff CallInfo.argIDs(callInfo, argIDs); for (int i = 0; i < args.size(); i++) { - VH_IntArray.set(argIDs, (long) i, args.get(i).id.ordinal()); + argIDs.setAtIndex(ValueLayout.JAVA_INT, i, args.get(i).id.ordinal()); } List argLayouts = new ArrayList<>(); @@ -197,10 +195,10 @@ private static class CallInfo { static final VarHandle VH_argIDs = LAYOUT.varHandle(groupElement("argIDs")); static void writeback(MemorySegment seg, MemorySegment addr) { - VH_writeback.set(seg, addr); + VH_writeback.set(seg, 0L, addr); } static void argIDs(MemorySegment seg, MemorySegment addr) { - VH_argIDs.set(seg, addr); + VH_argIDs.set(seg, 0L, addr); } } @@ -219,7 +217,9 @@ private Arg(NativeType id, MemoryLayout layout, TestValue value, MethodHandle ge } private static Arg primitiveArg(NativeType id, MemoryLayout layout, TestValue value) { - return new Arg(id, layout, value, layout.varHandle().toMethodHandle(VarHandle.AccessMode.GET)); + MethodHandle getterHandle = layout.varHandle().toMethodHandle(VarHandle.AccessMode.GET); + getterHandle = MethodHandles.insertArguments(getterHandle, 1, 0L); // align signature with getter for structs + return new Arg(id, layout, value, getterHandle); } private static Arg structArg(NativeType id, MemoryLayout layout, TestValue value) { diff --git a/test/jdk/java/foreign/TestVarHandleCombinators.java b/test/jdk/java/foreign/TestVarHandleCombinators.java index d7c2cb700df..ccf12b9fdee 100644 --- a/test/jdk/java/foreign/TestVarHandleCombinators.java +++ b/test/jdk/java/foreign/TestVarHandleCombinators.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @run testng TestVarHandleCombinators */ @@ -44,7 +43,7 @@ public class TestVarHandleCombinators { @Test public void testElementAccess() { - VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_BYTE); + VarHandle vh = ValueLayout.JAVA_BYTE.varHandle(); byte[] arr = { 0, 0, -1, 0 }; MemorySegment segment = MemorySegment.ofArray(arr); @@ -53,7 +52,7 @@ public void testElementAccess() { @Test(expectedExceptions = IllegalArgumentException.class) public void testUnalignedElement() { - VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_BYTE.withByteAlignment(4)); + VarHandle vh = ValueLayout.JAVA_BYTE.withByteAlignment(4).varHandle(); MemorySegment segment = MemorySegment.ofArray(new byte[4]); vh.get(segment, 2L); //should throw //FIXME: the VH only checks the alignment of the segment, which is fine if the VH is derived from layouts, @@ -63,7 +62,7 @@ public void testUnalignedElement() { @Test public void testAlign() { - VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_BYTE.withByteAlignment(2)); + VarHandle vh = ValueLayout.JAVA_BYTE.withByteAlignment(2).varHandle(); Arena scope = Arena.ofAuto(); MemorySegment segment = scope.allocate(1L, 2); @@ -73,8 +72,7 @@ public void testAlign() { @Test public void testByteOrderLE() { - VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_SHORT_UNALIGNED - .withOrder(ByteOrder.LITTLE_ENDIAN)); + VarHandle vh = ValueLayout.JAVA_SHORT_UNALIGNED.withOrder(ByteOrder.LITTLE_ENDIAN).varHandle(); byte[] arr = new byte[2]; MemorySegment segment = MemorySegment.ofArray(arr); vh.set(segment, 0L, (short) 0xFF); @@ -84,8 +82,7 @@ public void testByteOrderLE() { @Test public void testByteOrderBE() { - VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_SHORT_UNALIGNED - .withOrder(ByteOrder.BIG_ENDIAN)); + VarHandle vh = ValueLayout.JAVA_SHORT_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN).varHandle(); byte[] arr = new byte[2]; MemorySegment segment = MemorySegment.ofArray(arr); vh.set(segment, 0L, (short) 0xFF); @@ -100,7 +97,7 @@ public void testNestedSequenceAccess() { //[10 : [5 : [x32 i32]]] - VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT); + VarHandle vh = ValueLayout.JAVA_INT.varHandle(); int count = 0; try (Arena arena = Arena.ofConfined()) { MemorySegment segment = arena.allocate(inner_size * outer_size * 8, 4); diff --git a/test/jdk/java/foreign/UpcallTestHelper.java b/test/jdk/java/foreign/UpcallTestHelper.java index bbfa44aa346..1c2ca8aee80 100644 --- a/test/jdk/java/foreign/UpcallTestHelper.java +++ b/test/jdk/java/foreign/UpcallTestHelper.java @@ -56,7 +56,6 @@ public Output runInNewProcess(Class target, boolean useSpec, String... progra assert !target.isArray(); List command = new ArrayList<>(List.of( - "--enable-preview", "--enable-native-access=ALL-UNNAMED", "-Djava.library.path=" + System.getProperty("java.library.path"), "-Djdk.internal.foreign.UpcallLinker.USE_SPEC=" + useSpec, diff --git a/test/jdk/java/foreign/arraystructs/TestArrayStructs.java b/test/jdk/java/foreign/arraystructs/TestArrayStructs.java index 997de3f99de..b1cd87a33a8 100644 --- a/test/jdk/java/foreign/arraystructs/TestArrayStructs.java +++ b/test/jdk/java/foreign/arraystructs/TestArrayStructs.java @@ -23,9 +23,7 @@ /* * @test id=specialized - * @enablePreview * @library ../ - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign * @run testng/othervm @@ -37,9 +35,7 @@ /* * @test id=interpreted - * @enablePreview * @library ../ - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires (!(os.name == "Mac OS X" & os.arch == "aarch64") | jdk.foreign.linker != "FALLBACK") * @modules java.base/jdk.internal.foreign * @run testng/othervm diff --git a/test/jdk/java/foreign/callarranger/TestLayoutEquality.java b/test/jdk/java/foreign/callarranger/TestLayoutEquality.java index 2da5c0f6105..0f431489496 100644 --- a/test/jdk/java/foreign/callarranger/TestLayoutEquality.java +++ b/test/jdk/java/foreign/callarranger/TestLayoutEquality.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign.abi * @modules java.base/jdk.internal.foreign.layout diff --git a/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java index 78fe1292089..ae08f1c9be4 100644 --- a/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestLinuxAArch64CallArranger.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @requires sun.arch.data.model == "64" * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign diff --git a/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java index 278808593c7..30119db72e8 100644 --- a/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestMacOsAArch64CallArranger.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @requires sun.arch.data.model == "64" * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign diff --git a/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java b/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java index 338288985fa..f2486239645 100644 --- a/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestRISCV64CallArranger.java @@ -26,7 +26,6 @@ /* * @test - * @enablePreview * @requires sun.arch.data.model == "64" * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign diff --git a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java index ceb23f7ea06..53317b22dc0 100644 --- a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign * java.base/jdk.internal.foreign.abi diff --git a/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java index 2e0b42cd48e..4c612ef868c 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsAArch64CallArranger.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign * java.base/jdk.internal.foreign.abi diff --git a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java index 8257eaa7eae..3f47952dd83 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java @@ -24,7 +24,6 @@ /* * @test - * @enablePreview * @requires sun.arch.data.model == "64" * @compile platform/PlatformLayouts.java * @modules java.base/jdk.internal.foreign diff --git a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java index dbd17466e10..51c91ce0f96 100644 --- a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java +++ b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java @@ -23,9 +23,7 @@ /* * @test - * @enablePreview * @library ../ /test/lib - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestCaptureCallState */ @@ -63,16 +61,12 @@ public class TestCaptureCallState extends NativeTestHelper { } } - private record SaveValuesCase(String nativeTarget, FunctionDescriptor nativeDesc, boolean trivial, String threadLocalName, Consumer resultCheck) {} + private record SaveValuesCase(String nativeTarget, FunctionDescriptor nativeDesc, String threadLocalName, Consumer resultCheck) {} @Test(dataProvider = "cases") public void testSavedThreadLocal(SaveValuesCase testCase) throws Throwable { - List options = new ArrayList<>(); - options.add(Linker.Option.captureCallState(testCase.threadLocalName())); - if (testCase.trivial()) { - options.add(Linker.Option.isTrivial()); - } - MethodHandle handle = downcallHandle(testCase.nativeTarget(), testCase.nativeDesc(), options.toArray(Linker.Option[]::new)); + Linker.Option stl = Linker.Option.captureCallState(testCase.threadLocalName()); + MethodHandle handle = downcallHandle(testCase.nativeTarget(), testCase.nativeDesc(), stl); StructLayout capturedStateLayout = Linker.Option.captureStateLayout(); VarHandle errnoHandle = capturedStateLayout.varHandle(groupElement(testCase.threadLocalName())); @@ -85,7 +79,7 @@ public void testSavedThreadLocal(SaveValuesCase testCase) throws Throwable { ? handle.invoke(arena, saveSeg, testValue) : handle.invoke(saveSeg, testValue); testCase.resultCheck().accept(result); - int savedErrno = (int) errnoHandle.get(saveSeg); + int savedErrno = (int) errnoHandle.get(saveSeg, 0L); assertEquals(savedErrno, testValue); } } @@ -105,44 +99,36 @@ public void testInvalidCaptureSegment(MemorySegment captureSegment, } } - interface CaseAdder { - void addCase(String nativeTarget, FunctionDescriptor nativeDesc, String threadLocalName, Consumer resultCheck); - } - @DataProvider public static Object[][] cases() { List cases = new ArrayList<>(); - CaseAdder adder = (nativeTarget, nativeDesc, threadLocalName, resultCheck) -> { - cases.add(new SaveValuesCase(nativeTarget, nativeDesc, false, threadLocalName, resultCheck)); - cases.add(new SaveValuesCase(nativeTarget, nativeDesc, true, threadLocalName, resultCheck)); - }; - adder.addCase("set_errno_V", FunctionDescriptor.ofVoid(JAVA_INT), "errno", o -> {}); - adder.addCase("set_errno_I", FunctionDescriptor.of(JAVA_INT, JAVA_INT), "errno", o -> assertEquals((int) o, 42)); - adder.addCase("set_errno_D", FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT), "errno", o -> assertEquals((double) o, 42.0)); - - structCase(adder, "SL", Map.of(JAVA_LONG.withName("x"), 42L)); - structCase(adder, "SLL", Map.of(JAVA_LONG.withName("x"), 42L, - JAVA_LONG.withName("y"), 42L)); - structCase(adder, "SLLL", Map.of(JAVA_LONG.withName("x"), 42L, - JAVA_LONG.withName("y"), 42L, - JAVA_LONG.withName("z"), 42L)); - structCase(adder, "SD", Map.of(JAVA_DOUBLE.withName("x"), 42D)); - structCase(adder, "SDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, - JAVA_DOUBLE.withName("y"), 42D)); - structCase(adder, "SDDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, - JAVA_DOUBLE.withName("y"), 42D, - JAVA_DOUBLE.withName("z"), 42D)); + cases.add(new SaveValuesCase("set_errno_V", FunctionDescriptor.ofVoid(JAVA_INT), "errno", o -> {})); + cases.add(new SaveValuesCase("set_errno_I", FunctionDescriptor.of(JAVA_INT, JAVA_INT), "errno", o -> assertEquals((int) o, 42))); + cases.add(new SaveValuesCase("set_errno_D", FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT), "errno", o -> assertEquals((double) o, 42.0))); + + cases.add(structCase("SL", Map.of(JAVA_LONG.withName("x"), 42L))); + cases.add(structCase("SLL", Map.of(JAVA_LONG.withName("x"), 42L, + JAVA_LONG.withName("y"), 42L))); + cases.add(structCase("SLLL", Map.of(JAVA_LONG.withName("x"), 42L, + JAVA_LONG.withName("y"), 42L, + JAVA_LONG.withName("z"), 42L))); + cases.add(structCase("SD", Map.of(JAVA_DOUBLE.withName("x"), 42D))); + cases.add(structCase("SDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, + JAVA_DOUBLE.withName("y"), 42D))); + cases.add(structCase("SDDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, + JAVA_DOUBLE.withName("y"), 42D, + JAVA_DOUBLE.withName("z"), 42D))); if (IS_WINDOWS) { - adder.addCase("SetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "GetLastError", o -> {}); - adder.addCase("WSASetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "WSAGetLastError", o -> {}); + cases.add(new SaveValuesCase("SetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "GetLastError", o -> {})); + cases.add(new SaveValuesCase("WSASetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "WSAGetLastError", o -> {})); } return cases.stream().map(tc -> new Object[] {tc}).toArray(Object[][]::new); } - static void structCase(CaseAdder adder, String name, Map fields) { + static SaveValuesCase structCase(String name, Map fields) { StructLayout layout = MemoryLayout.structLayout(fields.keySet().toArray(MemoryLayout[]::new)); Consumer check = o -> {}; @@ -150,10 +136,10 @@ static void structCase(CaseAdder adder, String name, Map f MemoryLayout fieldLayout = field.getKey(); VarHandle fieldHandle = layout.varHandle(MemoryLayout.PathElement.groupElement(fieldLayout.name().get())); Object value = field.getValue(); - check = check.andThen(o -> assertEquals(fieldHandle.get(o), value)); + check = check.andThen(o -> assertEquals(fieldHandle.get(o, 0L), value)); } - adder.addCase("set_errno_" + name, FunctionDescriptor.of(layout, JAVA_INT), "errno", check); + return new SaveValuesCase("set_errno_" + name, FunctionDescriptor.of(layout, JAVA_INT), "errno", check); } @DataProvider diff --git a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java index 84016827a57..35d938ec1d3 100644 --- a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @library /test/lib * @modules java.base/sun.nio.ch * @key randomness diff --git a/test/jdk/java/foreign/channels/TestSocketChannels.java b/test/jdk/java/foreign/channels/TestSocketChannels.java index 445e0a9a236..e2cb012a508 100644 --- a/test/jdk/java/foreign/channels/TestSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestSocketChannels.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @library /test/lib * @modules java.base/sun.nio.ch * @key randomness diff --git a/test/jdk/java/foreign/dontrelease/TestDontRelease.java b/test/jdk/java/foreign/dontrelease/TestDontRelease.java index 0a9a0e4bd65..ba669953799 100644 --- a/test/jdk/java/foreign/dontrelease/TestDontRelease.java +++ b/test/jdk/java/foreign/dontrelease/TestDontRelease.java @@ -23,10 +23,8 @@ /* * @test - * @enablePreview * @library ../ /test/lib * @modules java.base/jdk.internal.ref java.base/jdk.internal.foreign - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestDontRelease */ diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java index 433daee7ffd..9dd228f5152 100644 --- a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -23,19 +23,16 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires !vm.musl * * @library /test/lib * @build TestEnableNativeAccess * panama_module/* - * org.openjdk.foreigntest.PanamaMainUnnamedModule + * org.openjdk.foreigntest.unnamed.PanamaMainUnnamedModule * @run testng/othervm/timeout=180 TestEnableNativeAccess * @summary Basic test for java --enable-native-access */ -import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; @@ -57,75 +54,7 @@ */ @Test -public class TestEnableNativeAccess { - - static final String MODULE_PATH = System.getProperty("jdk.module.path"); - - static final String PANAMA_MAIN = "panama_module/org.openjdk.foreigntest.PanamaMainDirect"; - static final String PANAMA_REFLECTION = "panama_module/org.openjdk.foreigntest.PanamaMainReflection"; - static final String PANAMA_INVOKE = "panama_module/org.openjdk.foreigntest.PanamaMainInvoke"; - static final String PANAMA_JNI = "panama_module/org.openjdk.foreigntest.PanamaMainJNI"; - static final String UNNAMED = "org.openjdk.foreigntest.PanamaMainUnnamedModule"; - - /** - * Represents the expected result of a test. - */ - static final class Result { - private final boolean success; - private final List expectedOutput = new ArrayList<>(); - private final List notExpectedOutput = new ArrayList<>(); - - Result(boolean success) { - this.success = success; - } - - Result expect(String msg) { - expectedOutput.add(msg); - return this; - } - - Result doNotExpect(String msg) { - notExpectedOutput.add(msg); - return this; - } - - boolean shouldSucceed() { - return success; - } - - Stream expectedOutput() { - return expectedOutput.stream(); - } - - Stream notExpectedOutput() { - return notExpectedOutput.stream(); - } - - @Override - public String toString() { - String s = (success) ? "success" : "failure"; - for (String msg : expectedOutput) { - s += "/" + msg; - } - return s; - } - } - - static Result success() { - return new Result(true); - } - - static Result successNoWarning() { - return success().doNotExpect("WARNING"); - } - - static Result successWithWarning(String moduleName) { - return success().expect("WARNING").expect("--enable-native-access=" + moduleName); - } - - static Result failWithWarning(String expectedOutput) { - return new Result(false).expect(expectedOutput).expect("WARNING"); - } +public class TestEnableNativeAccess extends TestEnableNativeAccessBase { @DataProvider(name = "succeedCases") public Object[][] succeedCases() { @@ -150,21 +79,6 @@ public Object[][] succeedCases() { }; } - /** - * Checks an expected result with the output captured by the given - * OutputAnalyzer. - */ - void checkResult(Result expectedResult, OutputAnalyzer outputAnalyzer) { - expectedResult.expectedOutput().forEach(outputAnalyzer::shouldContain); - expectedResult.notExpectedOutput().forEach(outputAnalyzer::shouldNotContain); - int exitValue = outputAnalyzer.getExitValue(); - if (expectedResult.shouldSucceed()) { - assertTrue(exitValue == 0); - } else { - assertTrue(exitValue != 0); - } - } - /** * Runs the test to execute the given test action. The VM is run with the * given VM options and the output checked to see that it matches the @@ -176,8 +90,8 @@ OutputAnalyzer run(String action, String cls, Result expectedResult, String... v Stream s1 = Stream.concat( Stream.of(vmopts), Stream.of("-Djava.library.path=" + System.getProperty("java.library.path"))); - Stream s2 = cls.equals(UNNAMED) ? Stream.of("--enable-preview", "-p", MODULE_PATH, cls, action) - : Stream.of("--enable-preview", "-p", MODULE_PATH, "-m", cls, action); + Stream s2 = cls.equals(UNNAMED) ? Stream.of("-p", MODULE_PATH, cls, action) + : Stream.of("-p", MODULE_PATH, "-m", cls, action); String[] opts = Stream.concat(s1, s2).toArray(String[]::new); OutputAnalyzer outputAnalyzer = ProcessTools .executeTestJava(opts) @@ -199,7 +113,7 @@ public void testSucceed(String action, String cls, Result expectedResult, String public void testWarnFirstAccess() throws Exception { List output1 = run("panama_enable_native_access_first", PANAMA_MAIN, successWithWarning("panama")).asLines(); - assertTrue(count(output1, "WARNING") == 3); // 3 on first access, none on subsequent access + assertTrue(count(output1, "WARNING") == 4); // 4 on first access, none on subsequent access } /** diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java new file mode 100644 index 00000000000..b5afb727997 --- /dev/null +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessBase.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.List; +import java.util.ArrayList; +import java.util.stream.Stream; + +import jdk.test.lib.process.OutputAnalyzer; + +import static org.testng.Assert.*; + +public class TestEnableNativeAccessBase { + static final String MODULE_PATH = System.getProperty("jdk.module.path"); + + static final String PANAMA_MAIN_CLS = "org.openjdk.foreigntest.PanamaMainDirect"; + static final String PANAMA_MAIN = "panama_module/" + PANAMA_MAIN_CLS; + static final String PANAMA_REFLECTION_CLS = "org.openjdk.foreigntest.PanamaMainReflection"; + static final String PANAMA_REFLECTION = "panama_module/" + PANAMA_REFLECTION_CLS; + static final String PANAMA_INVOKE_CLS = "org.openjdk.foreigntest.PanamaMainInvoke"; + static final String PANAMA_INVOKE = "panama_module/" + PANAMA_INVOKE_CLS; + static final String PANAMA_JNI_CLS = "org.openjdk.foreigntest.PanamaMainJNI"; + static final String PANAMA_JNI = "panama_module/" + PANAMA_JNI_CLS; + static final String UNNAMED = "org.openjdk.foreigntest.unnamed.PanamaMainUnnamedModule"; + + /** + * Represents the expected result of a test. + */ + static final class Result { + private final boolean success; + private final List expectedOutput = new ArrayList<>(); + private final List notExpectedOutput = new ArrayList<>(); + + Result(boolean success) { + this.success = success; + } + + Result expect(String msg) { + expectedOutput.add(msg); + return this; + } + + Result doNotExpect(String msg) { + notExpectedOutput.add(msg); + return this; + } + + boolean shouldSucceed() { + return success; + } + + Stream expectedOutput() { + return expectedOutput.stream(); + } + + Stream notExpectedOutput() { + return notExpectedOutput.stream(); + } + + @Override + public String toString() { + String s = (success) ? "success" : "failure"; + for (String msg : expectedOutput) { + s += "/" + msg; + } + return s; + } + + } + + static Result success() { + return new Result(true); + } + + static Result successNoWarning() { + return success().doNotExpect("WARNING"); + } + + static Result successWithWarning(String moduleName) { + return success().expect("WARNING").expect("--enable-native-access=" + moduleName); + } + + static Result failWithWarning(String expectedOutput) { + return new Result(false).expect(expectedOutput).expect("WARNING"); + } + + static Result failWithError(String expectedOutput) { + return new Result(false).expect(expectedOutput); + } + + /** + * Checks an expected result with the output captured by the given + * OutputAnalyzer. + */ + void checkResult(Result expectedResult, OutputAnalyzer outputAnalyzer) { + expectedResult.expectedOutput().forEach(outputAnalyzer::shouldContain); + expectedResult.notExpectedOutput().forEach(outputAnalyzer::shouldNotContain); + int exitValue = outputAnalyzer.getExitValue(); + if (expectedResult.shouldSucceed()) { + assertTrue(exitValue == 0); + } else { + assertTrue(exitValue != 0); + } + } +} diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java index 947ee46b3c7..fa09b0eb414 100644 --- a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires !vm.musl * * @library /test/lib @@ -37,80 +35,15 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Stream; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import static org.testng.Assert.*; @Test -public class TestEnableNativeAccessDynamic { - - static final String MODULE_PATH = System.getProperty("jdk.module.path"); - - static final String PANAMA_MAIN = "panama_module/org.openjdk.foreigntest.PanamaMainDirect"; - static final String PANAMA_REFLECTION = "panama_module/org.openjdk.foreigntest.PanamaMainReflection"; - static final String PANAMA_INVOKE = "panama_module/org.openjdk.foreigntest.PanamaMainInvoke"; - static final String PANAMA_JNI = "panama_module/org.openjdk.foreigntest.PanamaMainJNI"; - - /** - * Represents the expected result of a test. - */ - static final class Result { - private final boolean success; - private final List expectedOutput = new ArrayList<>(); - private final List notExpectedOutput = new ArrayList<>(); - - Result(boolean success) { - this.success = success; - } - - Result expect(String msg) { - expectedOutput.add(msg); - return this; - } - - Result doNotExpect(String msg) { - notExpectedOutput.add(msg); - return this; - } - - boolean shouldSucceed() { - return success; - } - - Stream expectedOutput() { - return expectedOutput.stream(); - } - - Stream notExpectedOutput() { - return notExpectedOutput.stream(); - } - - @Override - public String toString() { - String s = (success) ? "success" : "failure"; - for (String msg : expectedOutput) { - s += "/" + msg; - } - return s; - } - } - - static Result success() { - return new Result(true); - } - - static Result successNoWarning() { - return success().doNotExpect("WARNING"); - } - - static Result failWithError(String expectedOutput) { - return new Result(false).expect(expectedOutput); - } +public class TestEnableNativeAccessDynamic extends TestEnableNativeAccessBase { @DataProvider(name = "succeedCases") public Object[][] succeedCases() { @@ -131,21 +64,6 @@ public Object[][] failureCases() { }; } - /** - * Checks an expected result with the output captured by the given - * OutputAnalyzer. - */ - void checkResult(Result expectedResult, OutputAnalyzer outputAnalyzer) { - expectedResult.expectedOutput().forEach(outputAnalyzer::shouldContain); - expectedResult.notExpectedOutput().forEach(outputAnalyzer::shouldNotContain); - int exitValue = outputAnalyzer.getExitValue(); - if (expectedResult.shouldSucceed()) { - assertTrue(exitValue == 0); - } else { - assertTrue(exitValue != 0); - } - } - /** * Runs the test to execute the given test action. The VM is run with the * given VM options and the output checked to see that it matches the @@ -155,7 +73,6 @@ OutputAnalyzer run(String action, String moduleAndCls, boolean enableNativeAcces Result expectedResult, boolean panamaModuleInBootLayer) throws Exception { List list = new ArrayList<>(); - list.add("--enable-preview"); if (panamaModuleInBootLayer) { list.addAll(List.of("-p", MODULE_PATH)); list.add("--add-modules=panama_module"); diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java new file mode 100644 index 00000000000..d75e827fbc6 --- /dev/null +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessJarManifest.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Basic test for Enable-Native-Access attribute in the + * manifest of a main application JAR + * @library /test/lib + * @requires jdk.foreign.linker != "UNSUPPORTED" + * @requires !vm.musl + * + * @enablePreview + * @build TestEnableNativeAccessJarManifest + * panama_module/* + * org.openjdk.foreigntest.unnamed.PanamaMainUnnamedModule + * @run testng TestEnableNativeAccessJarManifest + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.ArrayList; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.util.JarUtils; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +public class TestEnableNativeAccessJarManifest extends TestEnableNativeAccessBase { + + private static final String REINVOKER = "TestEnableNativeAccessJarManifest$Reinvoker"; + + static record Attribute(String name, String value) {} + + @Test(dataProvider = "cases") + public void testEnableNativeAccessInJarManifest(String action, String cls, Result expectedResult, + List attributes, List vmArgs, List programArgs) throws Exception { + Manifest man = new Manifest(); + Attributes attrs = man.getMainAttributes(); + attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + attrs.put(Attributes.Name.MAIN_CLASS, cls); + + for (Attribute attrib : attributes) { + attrs.put(new Attributes.Name(attrib.name()), attrib.value()); + } + + // create the JAR file with Test1 and Test2 + Path jarfile = Paths.get(action + ".jar"); + Files.deleteIfExists(jarfile); + + Path classes = Paths.get(System.getProperty("test.classes", "")); + JarUtils.createJarFile(jarfile, man, classes, Paths.get(cls.replace('.', '/') + ".class")); + + // java -jar test.jar + List command = new ArrayList<>(List.of( + "--enable-preview", + "-Djava.library.path=" + System.getProperty("java.library.path") + )); + command.addAll(vmArgs); + command.add("-jar"); + command.add(jarfile.toString()); + command.addAll(programArgs); + OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava(command.toArray(String[]::new)) + .outputTo(System.out) + .errorTo(System.out); + checkResult(expectedResult, outputAnalyzer); + } + + @DataProvider + public Object[][] cases() { + return new Object[][] { + // simple cases where a jar contains a single main class with no dependencies + { "panama_no_unnamed_module_native_access", UNNAMED, successWithWarning("ALL-UNNAMED"), + List.of(), List.of(), List.of() }, + { "panama_unnamed_module_native_access", UNNAMED, successNoWarning(), + List.of(new Attribute("Enable-Native-Access", "ALL-UNNAMED")), List.of(), List.of() }, + { "panama_unnamed_module_native_access_invalid", UNNAMED, + failWithError("Error: illegal value \"asdf\" for Enable-Native-Access manifest attribute. Only ALL-UNNAMED is allowed"), + List.of(new Attribute("Enable-Native-Access", "asdf")), List.of(), List.of() }, + + // more complex cases where a jar invokes a module on the module path that does native access + { "panama_enable_native_access_false", REINVOKER, successWithWarning("panama_module"), + List.of(new Attribute("Enable-Native-Access", "ALL-UNNAMED")), + List.of("-p", MODULE_PATH, "--add-modules=panama_module"), + List.of(PANAMA_MAIN_CLS) }, + { "panama_enable_native_access_reflection_false", REINVOKER, successWithWarning("panama_module"), + List.of(new Attribute("Enable-Native-Access", "ALL-UNNAMED")), + List.of("-p", MODULE_PATH, "--add-modules=panama_module"), + List.of(PANAMA_REFLECTION_CLS) }, + { "panama_enable_native_access_invoke_false", REINVOKER, successWithWarning("panama_module"), + List.of(new Attribute("Enable-Native-Access", "ALL-UNNAMED")), + List.of("-p", MODULE_PATH, "--add-modules=panama_module"), + List.of(PANAMA_INVOKE_CLS) }, + + { "panama_enable_native_access_true", REINVOKER, successNoWarning(), + List.of(new Attribute("Enable-Native-Access", "ALL-UNNAMED")), + List.of("-p", MODULE_PATH, "--add-modules=panama_module", "--enable-native-access=panama_module"), + List.of(PANAMA_MAIN_CLS) }, + { "panama_enable_native_access_reflection_true", REINVOKER, successNoWarning(), + List.of(new Attribute("Enable-Native-Access", "ALL-UNNAMED")), + List.of("-p", MODULE_PATH, "--add-modules=panama_module", "--enable-native-access=panama_module"), + List.of(PANAMA_REFLECTION_CLS) }, + { "panama_enable_native_access_invoke_true", REINVOKER, successNoWarning(), + List.of(new Attribute("Enable-Native-Access", "ALL-UNNAMED")), + List.of("-p", MODULE_PATH, "--add-modules=panama_module", "--enable-native-access=panama_module"), + List.of(PANAMA_INVOKE_CLS) } + }; + } + + public class Reinvoker { + public static void main(String[] args) throws Throwable { + Class realMainClass = Class.forName(args[0]); + realMainClass.getMethod("main", String[].class).invoke(null, (Object) new String[0]); + } + } +} diff --git a/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/PanamaMainUnnamedModule.java b/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/unnamed/PanamaMainUnnamedModule.java similarity index 98% rename from test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/PanamaMainUnnamedModule.java rename to test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/unnamed/PanamaMainUnnamedModule.java index a9bcb929a25..79c3827488e 100644 --- a/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/PanamaMainUnnamedModule.java +++ b/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/unnamed/PanamaMainUnnamedModule.java @@ -21,7 +21,7 @@ * questions. */ -package org.openjdk.foreigntest; +package org.openjdk.foreigntest.unnamed; import java.lang.foreign.*; import java.lang.foreign.Linker.Option; diff --git a/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/libLinkerInvokerUnnamed.cpp b/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/unnamed/libLinkerInvokerUnnamed.cpp similarity index 93% rename from test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/libLinkerInvokerUnnamed.cpp rename to test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/unnamed/libLinkerInvokerUnnamed.cpp index 0e339f82de0..271970817d7 100644 --- a/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/libLinkerInvokerUnnamed.cpp +++ b/test/jdk/java/foreign/enablenativeaccess/org/openjdk/foreigntest/unnamed/libLinkerInvokerUnnamed.cpp @@ -36,7 +36,7 @@ void call(void* ctxt) { extern "C" { JNIEXPORT void JNICALL - Java_org_openjdk_foreigntest_PanamaMainUnnamedModule_nativeLinker0(JNIEnv *env, jclass cls) { + Java_org_openjdk_foreigntest_unnamed_PanamaMainUnnamedModule_nativeLinker0(JNIEnv *env, jclass cls) { JavaVM* jvm; env->GetJavaVM(&jvm); run_in_new_thread_and_join(call, jvm); diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java deleted file mode 100644 index 484341b2094..00000000000 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMain.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package org.openjdk.foreigntest; - -import java.lang.foreign.*; - -public class PanamaMain { - public static void main(String[] args) { - System.out.println("Trying to obtain a downcall handle"); - Linker.nativeLinker().downcallHandle(FunctionDescriptor.ofVoid()); - System.out.println("Got downcall handle"); - } -} diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/libLinkerInvokerModule.cpp b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/libLinkerInvokerModule.cpp index ae6e929d8a0..6c09f4900de 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/libLinkerInvokerModule.cpp +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/libLinkerInvokerModule.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,6 +29,7 @@ typedef struct { jobject linker; jobject desc; jobject opts; + jthrowable exception; } Context; void call(void* arg) { @@ -39,6 +40,8 @@ void call(void* arg) { jmethodID nativeLinkerMethod = env->GetMethodID(linkerClass, "downcallHandle", "(Ljava/lang/foreign/FunctionDescriptor;[Ljava/lang/foreign/Linker$Option;)Ljava/lang/invoke/MethodHandle;"); env->CallVoidMethod(context->linker, nativeLinkerMethod, context->desc, context->opts); + context->exception = (jthrowable) env->NewGlobalRef(env->ExceptionOccurred()); + env->ExceptionClear(); context->jvm->DetachCurrentThread(); } @@ -51,8 +54,12 @@ extern "C" { context.desc = env->NewGlobalRef(desc); context.opts = env->NewGlobalRef(opts); run_in_new_thread_and_join(call, &context); + if (context.exception != nullptr) { + env->Throw(context.exception); // transfer exception to this thread + } env->DeleteGlobalRef(context.linker); env->DeleteGlobalRef(context.desc); env->DeleteGlobalRef(context.opts); + env->DeleteGlobalRef(context.exception); } } diff --git a/test/jdk/java/foreign/handles/Driver.java b/test/jdk/java/foreign/handles/Driver.java index bca6483cf5d..1abfa6963fb 100644 --- a/test/jdk/java/foreign/handles/Driver.java +++ b/test/jdk/java/foreign/handles/Driver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @build invoker_module/* lookup_module/* * @run testng/othervm --enable-native-access=invoker_module * lookup_module/handle.lookup.MethodHandleLookup diff --git a/test/jdk/java/foreign/largestub/TestLargeStub.java b/test/jdk/java/foreign/largestub/TestLargeStub.java index 791bf6d161e..eca50c8f791 100644 --- a/test/jdk/java/foreign/largestub/TestLargeStub.java +++ b/test/jdk/java/foreign/largestub/TestLargeStub.java @@ -23,9 +23,7 @@ /* * @test - * @enablePreview * @library ../ - * @requires jdk.foreign.linker != "UNSUPPORTED" * @modules java.base/jdk.internal.foreign * @run testng/othervm --enable-native-access=ALL-UNNAMED TestLargeStub */ diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java index 0fef99ed718..fd174c6dc7e 100644 --- a/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @compile lookup/Lookup.java * @compile invoker/Invoker.java * @run main/othervm --enable-native-access=ALL-UNNAMED TestLoaderLookup diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java index 5f9d54dddeb..019583f2baf 100644 --- a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,8 +29,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm TestLoaderLookupJNI */ public class TestLoaderLookupJNI { diff --git a/test/jdk/java/foreign/nested/TestNested.java b/test/jdk/java/foreign/nested/TestNested.java index d1124cc54b0..52c08680709 100644 --- a/test/jdk/java/foreign/nested/TestNested.java +++ b/test/jdk/java/foreign/nested/TestNested.java @@ -23,9 +23,7 @@ /* * @test - * @enablePreview * @library ../ /test/lib - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires jdk.foreign.linker != "FALLBACK" * @build NativeTestHelper * @run testng/othervm --enable-native-access=ALL-UNNAMED TestNested diff --git a/test/jdk/java/foreign/normalize/TestNormalize.java b/test/jdk/java/foreign/normalize/TestNormalize.java index acea16d1702..af80ff3494a 100644 --- a/test/jdk/java/foreign/normalize/TestNormalize.java +++ b/test/jdk/java/foreign/normalize/TestNormalize.java @@ -23,9 +23,7 @@ /* * @test - * @enablePreview * @library ../ - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm * --enable-native-access=ALL-UNNAMED * -Xbatch diff --git a/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java index 5933ccbcca9..d78e1a293d7 100644 --- a/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java +++ b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -23,9 +23,7 @@ /* * @test - * @enablePreview * @library ../ /test/lib - * @requires jdk.foreign.linker != "UNSUPPORTED" * @run testng/othervm --enable-native-access=ALL-UNNAMED TestPassHeapSegment */ diff --git a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java index c8e7fd58e3c..c21225575f9 100644 --- a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java @@ -23,8 +23,6 @@ /* * @test id=default_gc - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc != "Z" * @library /test/lib * @library ../ @@ -42,8 +40,6 @@ /* * @test id=ZSinglegen - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc.ZSinglegen * @library /test/lib * @library ../ @@ -62,8 +58,6 @@ /* * @test id=ZGenerational - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc.ZGenerational * @library /test/lib * @library ../ @@ -82,8 +76,6 @@ /* * @test id=shenandoah - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc.Shenandoah * @library /test/lib * @library ../ diff --git a/test/jdk/java/foreign/stackwalk/TestReentrantUpcalls.java b/test/jdk/java/foreign/stackwalk/TestReentrantUpcalls.java index 44ed4132765..e69b44b4aa0 100644 --- a/test/jdk/java/foreign/stackwalk/TestReentrantUpcalls.java +++ b/test/jdk/java/foreign/stackwalk/TestReentrantUpcalls.java @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @library /test/lib * @library ../ * @build jdk.test.whitebox.WhiteBox diff --git a/test/jdk/java/foreign/stackwalk/TestStackWalk.java b/test/jdk/java/foreign/stackwalk/TestStackWalk.java index 785a2b49a9d..5218792658f 100644 --- a/test/jdk/java/foreign/stackwalk/TestStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestStackWalk.java @@ -23,8 +23,6 @@ /* * @test id=default_gc - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc != "Z" * @library /test/lib * @library ../ @@ -42,8 +40,6 @@ /* * @test id=ZSinglegen - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc.ZSinglegen * @library /test/lib * @library ../ @@ -62,8 +58,6 @@ /* * @test id=ZGenerational - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc.ZGenerational * @library /test/lib * @library ../ @@ -82,8 +76,6 @@ /* * @test id=shenandoah - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires vm.gc.Shenandoah * @library /test/lib * @library ../ diff --git a/test/jdk/java/foreign/trivial/TestTrivial.java b/test/jdk/java/foreign/trivial/TestCritical.java similarity index 67% rename from test/jdk/java/foreign/trivial/TestTrivial.java rename to test/jdk/java/foreign/trivial/TestCritical.java index 5e7bd87ca26..df5783350a4 100644 --- a/test/jdk/java/foreign/trivial/TestTrivial.java +++ b/test/jdk/java/foreign/trivial/TestCritical.java @@ -23,10 +23,8 @@ /* * @test - * @enablePreview * @library ../ /test/lib - * @requires jdk.foreign.linker != "UNSUPPORTED" - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestTrivial + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestCritical */ import org.testng.annotations.Test; @@ -43,21 +41,21 @@ import static org.testng.Assert.assertEquals; -public class TestTrivial extends NativeTestHelper { +public class TestCritical extends NativeTestHelper { static { - System.loadLibrary("Trivial"); + System.loadLibrary("Critical"); } @Test public void testEmpty() throws Throwable { - MethodHandle handle = downcallHandle("empty", FunctionDescriptor.ofVoid(), Linker.Option.isTrivial()); + MethodHandle handle = downcallHandle("empty", FunctionDescriptor.ofVoid(), Linker.Option.critical()); handle.invokeExact(); } @Test public void testIdentity() throws Throwable { - MethodHandle handle = downcallHandle("identity", FunctionDescriptor.of(C_INT, C_INT), Linker.Option.isTrivial()); + MethodHandle handle = downcallHandle("identity", FunctionDescriptor.of(C_INT, C_INT), Linker.Option.critical()); int result = (int) handle.invokeExact(42); assertEquals(result, 42); } @@ -68,31 +66,16 @@ public void testWithReturnBuffer() throws Throwable { C_LONG_LONG.withName("x"), C_LONG_LONG.withName("y")); - MethodHandle handle = downcallHandle("with_return_buffer", FunctionDescriptor.of(bigLayout), Linker.Option.isTrivial()); + MethodHandle handle = downcallHandle("with_return_buffer", FunctionDescriptor.of(bigLayout), Linker.Option.critical()); VarHandle vhX = bigLayout.varHandle(MemoryLayout.PathElement.groupElement("x")); VarHandle vhY = bigLayout.varHandle(MemoryLayout.PathElement.groupElement("y")); try (Arena arena = Arena.ofConfined()) { MemorySegment result = (MemorySegment) handle.invokeExact((SegmentAllocator) arena); - long x = (long) vhX.get(result); + long x = (long) vhX.get(result, 0L); assertEquals(x, 10); - long y = (long) vhY.get(result); + long y = (long) vhY.get(result, 0L); assertEquals(y, 11); } } - @Test - public void testCaptureErrno() throws Throwable { - Linker.Option ccs = Linker.Option.captureCallState("errno"); - MethodHandle handle = downcallHandle("capture_errno", FunctionDescriptor.ofVoid(C_INT), Linker.Option.isTrivial(), ccs); - StructLayout capturedStateLayout = Linker.Option.captureStateLayout(); - VarHandle errnoHandle = capturedStateLayout.varHandle(MemoryLayout.PathElement.groupElement("errno")); - try (Arena arena = Arena.ofConfined()) { - MemorySegment captureSeg = arena.allocate(capturedStateLayout); - handle.invokeExact(captureSeg, 42); - int capturedErrno = (int) errnoHandle.get(captureSeg); - assertEquals(capturedErrno, 42); - } - } - - } diff --git a/test/jdk/java/foreign/trivial/TestTrivialUpcall.java b/test/jdk/java/foreign/trivial/TestCriticalUpcall.java similarity index 87% rename from test/jdk/java/foreign/trivial/TestTrivialUpcall.java rename to test/jdk/java/foreign/trivial/TestCriticalUpcall.java index 8e4c9f937c1..2172f0ceda5 100644 --- a/test/jdk/java/foreign/trivial/TestTrivialUpcall.java +++ b/test/jdk/java/foreign/trivial/TestCriticalUpcall.java @@ -23,11 +23,9 @@ /* * @test - * @enablePreview * @library ../ /test/lib - * @requires jdk.foreign.linker != "UNSUPPORTED" * @requires jdk.foreign.linker != "FALLBACK" - * @run testng/othervm --enable-native-access=ALL-UNNAMED TestTrivialUpcall + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestCriticalUpcall */ import org.testng.annotations.Test; @@ -40,7 +38,7 @@ import static org.testng.Assert.fail; -public class TestTrivialUpcall extends UpcallTestHelper { +public class TestCriticalUpcall extends UpcallTestHelper { @Test public void testUpcallFailure() throws IOException, InterruptedException { @@ -50,9 +48,9 @@ public void testUpcallFailure() throws IOException, InterruptedException { public static class Runner extends NativeTestHelper { public static void main(String[] args) throws Throwable { - System.loadLibrary("Trivial"); + System.loadLibrary("Critical"); - MethodHandle mh = downcallHandle("do_upcall", FunctionDescriptor.ofVoid(C_POINTER), Linker.Option.isTrivial()); + MethodHandle mh = downcallHandle("do_upcall", FunctionDescriptor.ofVoid(C_POINTER), Linker.Option.critical()); MemorySegment stub = upcallStub(Runner.class, "target", FunctionDescriptor.ofVoid()); mh.invokeExact(stub); } diff --git a/test/jdk/java/foreign/trivial/libTrivial.c b/test/jdk/java/foreign/trivial/libCritical.c similarity index 96% rename from test/jdk/java/foreign/trivial/libTrivial.c rename to test/jdk/java/foreign/trivial/libCritical.c index bc3159f417f..8a825f9d42f 100644 --- a/test/jdk/java/foreign/trivial/libTrivial.c +++ b/test/jdk/java/foreign/trivial/libCritical.c @@ -48,10 +48,6 @@ EXPORT struct Big with_return_buffer() { return b; } -EXPORT void capture_errno(int value) { - errno = value; -} - EXPORT void do_upcall(void(*f)(void)) { f(); } diff --git a/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java index c8adcbdec5b..f4ecbb44145 100644 --- a/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java +++ b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java @@ -23,9 +23,7 @@ /* * @test id=default_gc - * @enablePreview * @bug 8277602 - * @requires jdk.foreign.linker != "UNSUPPORTED" * @library /test/lib * @library ../ * @build jdk.test.whitebox.WhiteBox diff --git a/test/jdk/java/foreign/virtual/TestVirtualCalls.java b/test/jdk/java/foreign/virtual/TestVirtualCalls.java index a48b3e93280..58c0d4c9afd 100644 --- a/test/jdk/java/foreign/virtual/TestVirtualCalls.java +++ b/test/jdk/java/foreign/virtual/TestVirtualCalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -23,8 +23,6 @@ /* * @test - * @enablePreview - * @requires jdk.foreign.linker != "UNSUPPORTED" * @library ../ * @run testng/othervm * --enable-native-access=ALL-UNNAMED diff --git a/test/jdk/java/lang/Thread/jni/AttachCurrentThread/AttachTest.java b/test/jdk/java/lang/Thread/jni/AttachCurrentThread/AttachTest.java index b93e7918014..7e1d9444478 100644 --- a/test/jdk/java/lang/Thread/jni/AttachCurrentThread/AttachTest.java +++ b/test/jdk/java/lang/Thread/jni/AttachCurrentThread/AttachTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -38,10 +38,10 @@ * @summary Test native threads attaching implicitly to the VM by means of an upcall * @requires (os.family == "linux" | os.family == "mac") & (sun.arch.data.model == "64") * @library /test/lib - * @compile --enable-preview -source ${jdk.version} ImplicitAttach.java - * @run main AttachTest --enable-preview --enable-native-access=ALL-UNNAMED ImplicitAttach 1 - * @run main AttachTest --enable-preview --enable-native-access=ALL-UNNAMED ImplicitAttach 2 - * @run main AttachTest --enable-preview --enable-native-access=ALL-UNNAMED ImplicitAttach 4 + * @compile ImplicitAttach.java + * @run main AttachTest --enable-native-access=ALL-UNNAMED ImplicitAttach 1 + * @run main AttachTest --enable-native-access=ALL-UNNAMED ImplicitAttach 2 + * @run main AttachTest --enable-native-access=ALL-UNNAMED ImplicitAttach 4 */ import java.util.stream.Stream; diff --git a/test/jdk/java/lang/invoke/VarHandles/IndirectVarHandleTest.java b/test/jdk/java/lang/invoke/VarHandles/IndirectVarHandleTest.java index bf1b6f66401..db0fc4800a2 100644 --- a/test/jdk/java/lang/invoke/VarHandles/IndirectVarHandleTest.java +++ b/test/jdk/java/lang/invoke/VarHandles/IndirectVarHandleTest.java @@ -23,7 +23,6 @@ /* @test * @bug 8307508 - * @enablePreview * @run junit IndirectVarHandleTest * @summary Test VarHandle::isAccessModeSupported on indirect VarHandle * produced by MethodHandles.filterCoordinates diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java index 65329a4011a..fc706815bce 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules java.base/jdk.internal.access.foreign * @modules java.base/jdk.internal.foreign.layout * @@ -171,7 +170,7 @@ public void testExactBufferSet(Class arrayClass, Object testValue, SetBufferX @Test(dataProvider = "dataSetMemorySegment") public void testExactSegmentSet(Class carrier, Object testValue, SetSegmentX setter) { - VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayouts.valueLayout(carrier, ByteOrder.nativeOrder())); + VarHandle vh = ValueLayouts.valueLayout(carrier, ByteOrder.nativeOrder()).varHandle(); try (Arena arena = Arena.ofConfined()) { MemorySegment seg = arena.allocate(8); doTest(vh, diff --git a/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java b/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java index 0597f2f8332..8f6ffb2eb40 100644 --- a/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java +++ b/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -37,7 +37,6 @@ /* * @test - * @enablePreview * @bug 8286637 * @summary Ensure that memory mapping beyond 32-bit range does not cause an * EXCEPTION_ACCESS_VIOLATION. diff --git a/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java b/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java index f46e9116d97..de89e318fc3 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, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -22,7 +22,6 @@ */ /* @test - * @enablePreview * @bug 8281412 * @summary Test FileChannel::map to MemorySegment with custom file channel * @run testng/othervm MapToMemorySegmentTest diff --git a/test/jdk/java/util/stream/test/TEST.properties b/test/jdk/java/util/stream/test/TEST.properties index 86434987c9e..2eb6c198177 100644 --- a/test/jdk/java/util/stream/test/TEST.properties +++ b/test/jdk/java/util/stream/test/TEST.properties @@ -6,6 +6,3 @@ lib.dirs = /lib/testlibrary/bootlib # Tests that must run in othervm mode othervm.dirs= /java/util/stream - -# To compile and run tests that use the foreign memory access API -enablePreview=true diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java index 6718c37e34f..029c0ad5b0c 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Byte128VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java index 63a5c012894..f6368b4972e 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Byte256VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java index fabb77f3a97..31cab63e85f 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Byte512VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java index eef32604590..69bdc215b8c 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Byte64VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java index 8a51dd67cff..3d4272f1803 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED * -XX:-TieredCompilation ByteMaxVectorLoadStoreTests diff --git a/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java index 005f3b2496c..f803bd85b4a 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Double128VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java index 53133964152..5b040a4fa41 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Double256VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java index 084d700a304..c5a77fb5c9b 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Double512VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java index d18a69c5175..db495f703ea 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Double64VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java index c6440367576..6f5efbd89b1 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED * -XX:-TieredCompilation DoubleMaxVectorLoadStoreTests diff --git a/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java index cd5e0ec09d7..79886797761 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Float128VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java index 1620b045de2..794e21ef648 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Float256VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java index be1b009be67..70e9863064b 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Float512VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java index 9f2a5fedba9..f8ebeab7db2 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Float64VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java index 0d9b2fa0bd4..61c9db74289 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED * -XX:-TieredCompilation FloatMaxVectorLoadStoreTests diff --git a/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java index 0de06ca4ec4..6bac67a5775 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Int128VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java index 8b9cfb876a8..6d5212d0268 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Int256VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java index 96957ec4903..fe3f55d65e5 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Int512VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java index e82c714654b..ce64e0fcd3c 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Int64VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java index 96f8aa9e38a..f61bb34f813 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED * -XX:-TieredCompilation IntMaxVectorLoadStoreTests diff --git a/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java index 85662ab0e88..5c36d67d0d6 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Long128VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java index c502c19d67d..c8f932fda56 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Long256VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java index 9485e1d2c06..825706ced04 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Long512VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java index 145f8e18718..ecbd349b279 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Long64VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java index ec0170c8779..e601af509a5 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED * -XX:-TieredCompilation LongMaxVectorLoadStoreTests diff --git a/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java index f404ee49139..e51ccfeec19 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Short128VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java index e6ba0a2f6b0..cbe0063168a 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Short256VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java index b4c2a899c4e..eb847075ea4 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Short512VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java index 229e41248d6..ad73af04b53 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm -XX:-TieredCompilation Short64VectorLoadStoreTests * diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java index 4f5ab531c75..6412897c2c7 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED * -XX:-TieredCompilation ShortMaxVectorLoadStoreTests diff --git a/test/jdk/jdk/incubator/vector/VectorReshapeTests.java b/test/jdk/jdk/incubator/vector/VectorReshapeTests.java index 5d70fa7483c..e663c797ffe 100644 --- a/test/jdk/jdk/incubator/vector/VectorReshapeTests.java +++ b/test/jdk/jdk/incubator/vector/VectorReshapeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -36,7 +36,6 @@ /** * @test - * @enablePreview * @modules jdk.incubator.vector * @modules java.base/jdk.internal.vm.annotation * @run testng/othervm/timeout=240 --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED diff --git a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template index bac451ae026..f9226d073b5 100644 --- a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template +++ b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,7 +23,6 @@ /* * @test - * @enablePreview * @modules jdk.incubator.vector java.base/jdk.internal.vm.annotation #if[MaxBit] * @run testng/othervm --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED diff --git a/test/langtools/tools/javac/RestrictedMethods.java b/test/langtools/tools/javac/RestrictedMethods.java index 4e3670f551c..3f79860add5 100644 --- a/test/langtools/tools/javac/RestrictedMethods.java +++ b/test/langtools/tools/javac/RestrictedMethods.java @@ -2,8 +2,8 @@ * @test /nodynamiccopyright/ * @bug 8316971 * @summary Smoke test for restricted method call warnings - * @compile/fail/ref=RestrictedMethods.out -Xlint:restricted -Werror -XDrawDiagnostics --enable-preview --source ${jdk.version} RestrictedMethods.java - * @compile -Werror --enable-preview --source ${jdk.version} RestrictedMethods.java + * @compile/fail/ref=RestrictedMethods.out -Xlint:restricted -Werror -XDrawDiagnostics RestrictedMethods.java + * @compile -Werror RestrictedMethods.java */ import java.lang.foreign.MemorySegment; diff --git a/test/langtools/tools/javac/RestrictedMethods.out b/test/langtools/tools/javac/RestrictedMethods.out index abf4e1ee1fb..e6ef28a68ca 100644 --- a/test/langtools/tools/javac/RestrictedMethods.out +++ b/test/langtools/tools/javac/RestrictedMethods.out @@ -3,7 +3,5 @@ RestrictedMethods.java:18:49: compiler.warn.restricted.method: java.lang.foreign RestrictedMethods.java:24:27: compiler.warn.restricted.method: java.lang.foreign.MemorySegment, reinterpret(long) RestrictedMethods.java:33:16: compiler.warn.restricted.method: java.lang.foreign.MemorySegment, reinterpret(long) - compiler.err.warnings.and.werror -- compiler.note.preview.filename: RestrictedMethods.java, DEFAULT -- compiler.note.preview.recompile 1 error 4 warnings diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java new file mode 100644 index 00000000000..ff73699bd30 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromSliceTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.lang.foreign; + +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.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) +public class AllocFromSliceTest extends CLayouts { + + @Param({"5", "20", "100", "500", "1000"}) + public int size; + public int start; + public byte[] arr; + + @Setup + public void setup() { + arr = new byte[1024]; + Random random = new Random(0); + random.nextBytes(arr); + start = random.nextInt(1024 - size); + } + + @Benchmark + public MemorySegment alloc_confined() { + Arena arena = Arena.ofConfined(); + MemorySegment segment = arena.allocate(size); + MemorySegment.copy(arr, start, segment, C_CHAR, 0, size); + arena.close(); + return segment; + } + + @Benchmark + public MemorySegment alloc_confined_slice() { + Arena arena = Arena.ofConfined(); + MemorySegment segment = arena.allocateFrom(C_CHAR, MemorySegment.ofArray(arr), C_CHAR, start, size); + arena.close(); + return segment; + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java new file mode 100644 index 00000000000..a0c5d5be289 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/AllocFromTest.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.lang.foreign; + +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.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.MemorySegment.Scope; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.ValueLayout; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) +public class AllocFromTest extends CLayouts { + + Arena arena = Arena.ofConfined(); + + SlicingPool pool = new SlicingPool(); + + @Param({"5", "20", "100", "500", "1000"}) + public int size; + public byte[] arr; + + @Setup + public void setup() { + arr = new byte[size]; + Random random = new Random(0); + random.nextBytes(arr); + } + + @Benchmark + public MemorySegment alloc_confined() { + Arena arena = Arena.ofConfined(); + MemorySegment segment = arena.allocateFrom(ValueLayout.JAVA_BYTE, arr); + arena.close(); + return segment; + } + + @Benchmark + public MemorySegment alloc_malloc_arena() { + MallocArena arena = new MallocArena(); + MemorySegment segment = arena.allocateFrom(ValueLayout.JAVA_BYTE, arr); + arena.close(); + return segment; + } + + @Benchmark + public MemorySegment alloc_unsafe_arena() { + UnsafeArena arena = new UnsafeArena(); + MemorySegment segment = arena.allocateFrom(ValueLayout.JAVA_BYTE, arr); + arena.close(); + return segment; + } + + @Benchmark + public MemorySegment alloc_pool_arena() { + Arena arena = pool.acquire(); + MemorySegment segment = arena.allocateFrom(ValueLayout.JAVA_BYTE, arr); + arena.close(); + return segment; + } + + static class SlicingPool { + final MemorySegment pool = Arena.ofAuto().allocate(1024); + boolean isAcquired = false; + + public Arena acquire() { + if (isAcquired) { + throw new IllegalStateException("An allocator is already in use"); + } + isAcquired = true; + return new SlicingPoolAllocator(); + } + + class SlicingPoolAllocator implements Arena { + + final Arena arena = Arena.ofConfined(); + final SegmentAllocator slicing = SegmentAllocator.slicingAllocator(pool); + + public MemorySegment allocate(long byteSize, long byteAlignment) { + return slicing.allocate(byteSize, byteAlignment) + .reinterpret(arena, null); + } + + @Override + public Scope scope() { + return arena.scope(); + } + + public void close() { + isAcquired = false; + arena.close(); + } + } + } + + public static class MallocArena implements Arena { + + final Arena arena = Arena.ofConfined(); + + @Override + public Scope scope() { + return arena.scope(); + } + + @Override + public void close() { + arena.close(); + } + + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + return CLayouts.allocateMemory(byteSize) + .reinterpret(byteSize, arena, CLayouts::freeMemory); + } + } + + public static class UnsafeArena implements Arena { + + final Arena arena = Arena.ofConfined(); + + @Override + public Scope scope() { + return arena.scope(); + } + + @Override + public void close() { + arena.close(); + } + + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + return MemorySegment.ofAddress(Utils.unsafe.allocateMemory(byteSize)) + .reinterpret(byteSize, arena, ms -> Utils.unsafe.freeMemory(ms.address())); + } + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java index a521192e924..3546fa1cca4 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -51,7 +51,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class BulkOps { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java b/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java index 7085f7af530..f15ad60834b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -69,7 +69,7 @@ public class CLayouts { * The {@code T*} native type. */ public static final AddressLayout C_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(C_CHAR)); + .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, C_CHAR)); private static Linker LINKER = Linker.nativeLinker(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java index 3e1614f32dc..ff7a8b66e16 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -41,7 +41,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class CallOverheadConstant { @Benchmark @@ -55,8 +55,8 @@ public void panama_blank() throws Throwable { } @Benchmark - public void panama_blank_trivial() throws Throwable { - func_trivial.invokeExact(); + public void panama_blank_critical() throws Throwable { + func_critical.invokeExact(); } @Benchmark @@ -70,8 +70,8 @@ public int panama_identity() throws Throwable { } @Benchmark - public int panama_identity_trivial() throws Throwable { - return (int) identity_trivial.invokeExact(10); + public int panama_identity_critical() throws Throwable { + return (int) identity_critical.invokeExact(10); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java index 26588b6bd08..2a305d26297 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -34,14 +34,14 @@ public class CallOverheadHelper extends CLayouts { static final Linker abi = Linker.nativeLinker(); static final MethodHandle func; - static final MethodHandle func_trivial; + static final MethodHandle func_critical; static final MethodHandle func_v; - static final MethodHandle func_trivial_v; + static final MethodHandle func_critical_v; static MemorySegment func_addr; static final MethodHandle identity; - static final MethodHandle identity_trivial; + static final MethodHandle identity_critical; static final MethodHandle identity_v; - static final MethodHandle identity_trivial_v; + static final MethodHandle identity_critical_v; static MemorySegment identity_addr; static final MethodHandle identity_struct; static final MethodHandle identity_struct_v; @@ -113,17 +113,17 @@ public class CallOverheadHelper extends CLayouts { MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); func_v = abi.downcallHandle(fd); - func_trivial_v = abi.downcallHandle(fd, Linker.Option.isTrivial()); + func_critical_v = abi.downcallHandle(fd, Linker.Option.critical()); func = insertArguments(func_v, 0, func_addr); - func_trivial = insertArguments(func_trivial_v, 0, func_addr); + func_critical = insertArguments(func_critical_v, 0, func_addr); } { identity_addr = loaderLibs.find("identity").orElseThrow(); FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT); identity_v = abi.downcallHandle(fd); - identity_trivial_v = abi.downcallHandle(fd, Linker.Option.isTrivial()); + identity_critical_v = abi.downcallHandle(fd, Linker.Option.critical()); identity = insertArguments(identity_v, 0, identity_addr); - identity_trivial = insertArguments(identity_trivial_v, 0, identity_addr); + identity_critical = insertArguments(identity_critical_v, 0, identity_addr); } identity_struct_addr = loaderLibs.find("identity_struct").orElseThrow(); identity_struct_v = abi.downcallHandle( diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java index 6797eda9924..21dd5eaac05 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -41,7 +41,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class CallOverheadVirtual { @Benchmark @@ -55,8 +55,8 @@ public void panama_blank() throws Throwable { } @Benchmark - public void panama_blank_trivial() throws Throwable { - func_trivial_v.invokeExact(func_addr); + public void panama_blank_critical() throws Throwable { + func_critical_v.invokeExact(func_addr); } @Benchmark @@ -109,8 +109,8 @@ public int panama_identity() throws Throwable { } @Benchmark - public int panama_identity_trivial() throws Throwable { - return (int) identity_trivial_v.invokeExact(identity_addr, 10); + public int panama_identity_critical() throws Throwable { + return (int) identity_critical_v.invokeExact(identity_addr, 10); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java b/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java index 1c9e886e146..c6e740113b8 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -24,16 +24,27 @@ package org.openjdk.bench.java.lang.foreign; import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; -import static java.lang.foreign.ValueLayout.*; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED; +import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED; /** - * Some useful Java {@link ValueLayout} and associated {@link ValueLayout#arrayElementVarHandle(int...)} var handles. + * Some useful Java {@link ValueLayout} and associated array var handles. */ public class JavaLayouts { - static final VarHandle VH_INT_UNALIGNED = JAVA_INT_UNALIGNED.arrayElementVarHandle(); + static final VarHandle VH_INT_UNALIGNED = arrayVarHandle(JAVA_INT_UNALIGNED); + static final VarHandle VH_INT = arrayVarHandle(JAVA_INT); - static final VarHandle VH_INT = JAVA_INT.arrayElementVarHandle(); + static final VarHandle VH_LONG_UNALIGNED = arrayVarHandle(JAVA_LONG_UNALIGNED); + static final VarHandle VH_LONG = arrayVarHandle(JAVA_LONG); + + private static VarHandle arrayVarHandle(ValueLayout layout) { + return MethodHandles.collectCoordinates(layout.varHandle(), + 1, MethodHandles.insertArguments(layout.scaleHandle(), 0, 0L)); + } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java index 0adbc72e5b4..57c8bd029ba 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(Scope.Benchmark) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class LinkUpcall extends CLayouts { static final Linker LINKER = Linker.nativeLinker(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java index c592c8c9599..05e764d7fe3 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverConstant extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java index 73a7f803164..db456f57aaa 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverNew extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java index 2fd596d8a36..feafb721028 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverNewHeap extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java index 46c4091a8bf..c1c04ebd8d7 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-preview", "--enable-native-access=ALL-UNNAMED" }) +@Fork(3) public class LoopOverNonConstant extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java index 2bfb3ef2a03..251d5621bcf 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverNonConstantFP { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java index 3b7b8052f5f..7db3bc14665 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -49,7 +49,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverNonConstantHeap extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java index 43ea54f6703..f1b9a81091f 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -55,7 +55,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverNonConstantMapped extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java index f3c440e5879..c64391f242b 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverNonConstantShared extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java index fd6ba441589..cf1c9097454 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -43,7 +43,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverOfAddress extends JavaLayouts { static final int ITERATIONS = 1_000_000; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java index 412786a2089..434d75bcd84 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverPollutedBuffer { static final int ELEM_SIZE = 1_000_000; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java index d396432d6e2..2077a47d86a 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -46,7 +46,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class LoopOverPollutedSegments extends JavaLayouts { static final int ELEM_SIZE = 1_000_000; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java index 2979547ba40..dc31042f5a0 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -49,7 +49,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-preview", "--enable-native-access=ALL-UNNAMED" }) +@Fork(3) public class LoopOverSlice { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java new file mode 100644 index 00000000000..4b6db5f9618 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentCopyUnsafe.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.foreign; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import sun.misc.Unsafe; + +import java.util.concurrent.TimeUnit; + +import static java.lang.foreign.ValueLayout.*; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3, jvmArgsAppend = {"--enable-native-access=ALL-UNNAMED"}) +public class MemorySegmentCopyUnsafe { + + static final Unsafe UNSAFE = Utils.unsafe; + + long src; + long dst; + + @Setup + public void setup() throws Throwable { + src = Arena.global().allocate(JAVA_INT).address(); + dst = Arena.global().allocate(JAVA_INT).address(); + } + + @Benchmark + public void panama() { + MemorySegment srcSeg = MemorySegment.ofAddress(src).reinterpret(JAVA_INT.byteSize()); + MemorySegment dstSeg = MemorySegment.ofAddress(dst).reinterpret(JAVA_INT.byteSize()); + dstSeg.copyFrom(srcSeg); + } + + @Benchmark + public void unsafe() { + UNSAFE.copyMemory(src, dst, JAVA_INT.byteSize()); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java new file mode 100644 index 00000000000..233c9672935 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentGetUnsafe.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.lang.foreign; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import sun.misc.Unsafe; + +import java.util.concurrent.TimeUnit; + +import static java.lang.foreign.ValueLayout.*; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3, jvmArgsAppend = {"--enable-native-access=ALL-UNNAMED"}) +public class MemorySegmentGetUnsafe { + + static final Unsafe UNSAFE = Utils.unsafe; + static final MethodHandle OF_ADDRESS_UNSAFE; + + static { + try { + OF_ADDRESS_UNSAFE = MethodHandles.lookup().findStatic(MemorySegmentGetUnsafe.class, + "ofAddressUnsafe", MethodType.methodType(MemorySegment.class, long.class)); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } + + static final VarHandle INT_HANDLE = adaptSegmentHandle(JAVA_INT.varHandle()); + + static VarHandle adaptSegmentHandle(VarHandle handle) { + handle = MethodHandles.insertCoordinates(handle, 1, 0L); + handle = MethodHandles.filterCoordinates(handle, 0, OF_ADDRESS_UNSAFE); + return handle; + } + + static MemorySegment ofAddressUnsafe(long address) { + return MemorySegment.ofAddress(address).reinterpret(JAVA_INT.byteSize()); + } + + long addr; + + @Setup + public void setup() throws Throwable { + addr = Arena.global().allocate(JAVA_INT).address(); + } + + @Benchmark + public int panama() { + return (int) INT_HANDLE.get(addr); + } + + @Benchmark + public int unsafe() { + return UNSAFE.getInt(addr); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentVsBits.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentVsBits.java index 9259fc4c56e..aead31138d0 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentVsBits.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySegmentVsBits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -58,7 +58,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = {"--enable-native-access=ALL-UNNAMED", "--enable-preview"}) +@Fork(3) public class MemorySegmentVsBits { public static final VarHandle LONG_ARRAY_VH = MethodHandles.byteArrayViewVarHandle(long[].class, BIG_ENDIAN); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java index fa4207709ed..cf1d079193a 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -46,7 +46,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class MemorySessionClose { static final int ALLOC_SIZE = 1024; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java index 1579951127e..2fcd444989f 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -52,7 +52,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class ParallelSum extends JavaLayouts { final static int CARRIER_SIZE = 4; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java b/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java index 097a435f37a..4114d258d08 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -43,7 +43,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class PointerInvoke extends CLayouts { Arena arena = Arena.ofConfined(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java b/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java index 90b7693db3d..5449d0d42d3 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -46,7 +46,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class QSort extends CLayouts { static final Linker abi = Linker.nativeLinker(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java index 63811c6d90c..83751d07eda 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -48,7 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class StrLenTest extends CLayouts { Arena arena = Arena.ofConfined(); @@ -92,27 +92,27 @@ public int jni_strlen() throws Throwable { @Benchmark public int panama_strlen() throws Throwable { try (Arena arena = Arena.ofConfined()) { - MemorySegment segment = arena.allocateUtf8String(str); + MemorySegment segment = arena.allocateFrom(str); return (int)STRLEN.invokeExact(segment); } } @Benchmark public int panama_strlen_ring() throws Throwable { - return (int)STRLEN.invokeExact(arenaAllocator.allocateUtf8String(str)); + return (int)STRLEN.invokeExact(arenaAllocator.allocateFrom(str)); } @Benchmark public int panama_strlen_pool() throws Throwable { Arena arena = pool.acquire(); - int l = (int) STRLEN.invokeExact(arena.allocateUtf8String(str)); + int l = (int) STRLEN.invokeExact(arena.allocateFrom(str)); arena.close(); return l; } @Benchmark public int panama_strlen_prefix() throws Throwable { - return (int)STRLEN.invokeExact(segmentAllocator.allocateUtf8String(str)); + return (int)STRLEN.invokeExact(segmentAllocator.allocateFrom(str)); } @Benchmark @@ -162,7 +162,7 @@ public MemorySegment allocate(long byteSize, long byteAlignment) { reset(); } MemorySegment res = current.allocate(byteSize, byteAlignment); - long lastOffset = segment.segmentOffset(res) + res.byteSize(); + long lastOffset = res.address() - segment.address() + res.byteSize(); rem = segment.byteSize() - lastOffset; return res; } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/TestAdaptVarHandles.java b/test/micro/org/openjdk/bench/java/lang/foreign/TestAdaptVarHandles.java index 05595646072..7ca70b31f49 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/TestAdaptVarHandles.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/TestAdaptVarHandles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -47,7 +47,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class TestAdaptVarHandles extends JavaLayouts { static class IntBox { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java b/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java index 40d09b7b762..e7380064b44 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -48,10 +48,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 1, jvmArgsAppend = { - "-Dforeign.restricted=permit", - "--enable-native-access", "ALL-UNNAMED", - "--enable-preview"}) +@Fork(1) public class TestLoadBytes { @Param("1024") private int size; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java index 2ba4ac2c414..6888f82e529 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -40,15 +40,11 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-preview", "--enable-native-access=ALL-UNNAMED" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class UnrolledAccess extends JavaLayouts { static final Unsafe U = Utils.unsafe; - static final VarHandle VH_LONG_UNALIGNED = JAVA_LONG_UNALIGNED.arrayElementVarHandle(); - - static final VarHandle VH_LONG = JAVA_LONG.arrayElementVarHandle(); - final static int SIZE = 1024; @State(Scope.Benchmark) diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java b/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java index e0de2fbfcb7..b627978c615 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -45,7 +45,7 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) +@Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED" }) public class Upcalls extends CLayouts { static final Linker abi = Linker.nativeLinker(); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java b/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java index 4f8f9638c24..b1e9bdf2987 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -47,14 +47,14 @@ @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @State(org.openjdk.jmh.annotations.Scope.Thread) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) public class VarHandleExact { static final VarHandle exact; static final VarHandle generic; static { - generic = MethodHandles.memorySegmentViewVarHandle(JAVA_INT); + generic = JAVA_INT.varHandle(); exact = generic.withInvokeExactBehavior(); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java index 9f1307f94a9..4d6b00287de 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -40,7 +40,7 @@ public non-sealed static abstract class OfDouble extends NativeType { } private static final AddressLayout UNSAFE_ADDRESS = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)); + .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, ValueLayout.JAVA_BYTE)); public final static class OfPointer extends NativeType { public AddressLayout layout() { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java index 13a96a2ab59..2c50e8d1be0 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -78,7 +78,7 @@ public static Pointer allocate(NativeType type, SegmentAllocator alloc } public static Pointer allocate(NativeType type, long size, SegmentAllocator allocator) { - MemorySegment segment = allocator.allocateArray(type.layout(), size); + MemorySegment segment = allocator.allocate(type.layout(), size); return new Pointer<>(segment); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java index cd13aa0290e..d4be11e675c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -46,7 +46,7 @@ @Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @OutputTimeUnit(TimeUnit.MILLISECONDS) -@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@Fork(3) @State(Scope.Benchmark) public class PointerBench { @@ -60,7 +60,7 @@ public class PointerBench { MemorySegment pointSegment = pointPointer.segment(); public static final AddressLayout UNSAFE_ADDRESS = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)); + .withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, ValueLayout.JAVA_BYTE)); @Setup public void setup() { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java b/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java index 27604fed6b8..fbcf3ba5528 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -68,19 +68,19 @@ public PanamaPoint(int x, int y) { } public void setX(int x) { - VH_x.set(segment, x); + VH_x.set(segment, 0L, x); } public int getX() { - return (int) VH_x.get(segment); + return (int) VH_x.get(segment, 0L); } public void setY(int y) { - VH_y.set(segment, y); + VH_y.set(segment, 0L, y); } public int getY() { - return (int) VH_y.get(segment); + return (int) VH_y.get(segment, 0L); } public double distanceTo(PanamaPoint other) { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java index 7ee14cbaee3..55248290f0e 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Rado Smogura. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -50,7 +50,6 @@ @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(value = 1, jvmArgsAppend = { "--add-modules=jdk.incubator.vector", - "--enable-preview", "--enable-native-access", "ALL-UNNAMED"}) public class MemorySegmentVectorAccess { private static final VectorSpecies SPECIES = VectorSpecies.ofLargestShape(byte.class); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java index 7a42a247b12..3ea1943e703 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -49,7 +49,6 @@ @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(value = 1, jvmArgsAppend = { "--add-modules=jdk.incubator.vector", - "--enable-preview", "--enable-native-access", "ALL-UNNAMED", "-Djdk.incubator.vector.VECTOR_ACCESS_OOB_CHECK=1"}) public class TestLoadStoreBytes { diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java index 2aec829fba8..d6c6531d3f8 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -52,7 +52,6 @@ @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(value = 1, jvmArgsAppend = { "--add-modules=jdk.incubator.vector", - "--enable-preview", "--enable-native-access", "ALL-UNNAMED"}) public class TestLoadStoreShorts { private static final VectorSpecies SPECIES = VectorSpecies.ofLargestShape(short.class); From 64ee3c99908964a7fa4475084ca4cade14fabef8 Mon Sep 17 00:00:00 2001 From: Evgeny Astigeevich Date: Thu, 12 Oct 2023 19:56:18 +0000 Subject: [PATCH 012/111] 8317266: Move nmethod::check_all_dependencies to codeCache.cpp and mark it NOT_PRODUCT Reviewed-by: kvn, dlong --- src/hotspot/share/code/codeCache.cpp | 50 +++++++++++++++++++++++++++- src/hotspot/share/code/nmethod.cpp | 45 ------------------------- src/hotspot/share/code/nmethod.hpp | 4 --- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 3bc1db70251..8c906fdb416 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1251,6 +1251,54 @@ void CodeCache::cleanup_inline_caches_whitebox() { // Keeps track of time spent for checking dependencies NOT_PRODUCT(static elapsedTimer dependentCheckTime;) +#ifndef PRODUCT +// Check if any of live methods dependencies have been invalidated. +// (this is expensive!) +static void check_live_nmethods_dependencies(DepChange& changes) { + // Checked dependencies are allocated into this ResourceMark + ResourceMark rm; + + // Turn off dependency tracing while actually testing dependencies. + FlagSetting fs(Dependencies::_verify_in_progress, true); + + typedef ResourceHashtable DepTable; + + DepTable* table = new DepTable(); + + // Iterate over live nmethods and check dependencies of all nmethods that are not + // marked for deoptimization. A particular dependency is only checked once. + NMethodIterator iter(NMethodIterator::only_not_unloading); + while(iter.next()) { + nmethod* nm = iter.method(); + // Only notify for live nmethods + if (!nm->is_marked_for_deoptimization()) { + for (Dependencies::DepStream deps(nm); deps.next(); ) { + // Construct abstraction of a dependency. + DependencySignature* current_sig = new DependencySignature(deps); + + // Determine if dependency is already checked. table->put(...) returns + // 'true' if the dependency is added (i.e., was not in the hashtable). + if (table->put(*current_sig, 1)) { + if (deps.check_dependency() != nullptr) { + // Dependency checking failed. Print out information about the failed + // dependency and finally fail with an assert. We can fail here, since + // dependency checking is never done in a product build. + tty->print_cr("Failed dependency:"); + changes.print(); + nm->print(); + nm->print_dependencies_on(tty); + assert(false, "Should have been marked for deoptimization"); + } + } + } + } + } +} +#endif + void CodeCache::mark_for_deoptimization(DeoptimizationScope* deopt_scope, KlassDepChange& changes) { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); @@ -1272,7 +1320,7 @@ void CodeCache::mark_for_deoptimization(DeoptimizationScope* deopt_scope, KlassD // Object pointers are used as unique identifiers for dependency arguments. This // is only possible if no safepoint, i.e., GC occurs during the verification code. dependentCheckTime.start(); - nmethod::check_all_dependencies(changes); + check_live_nmethods_dependencies(changes); dependentCheckTime.stop(); } #endif diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 51889df95f1..d0a02cb43eb 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -2148,51 +2148,6 @@ PcDesc* PcDescContainer::find_pc_desc_internal(address pc, bool approximate, con } } - -void nmethod::check_all_dependencies(DepChange& changes) { - // Checked dependencies are allocated into this ResourceMark - ResourceMark rm; - - // Turn off dependency tracing while actually testing dependencies. - NOT_PRODUCT( FlagSetting fs(Dependencies::_verify_in_progress, true)); - - typedef ResourceHashtable DepTable; - - DepTable* table = new DepTable(); - - // Iterate over live nmethods and check dependencies of all nmethods that are not - // marked for deoptimization. A particular dependency is only checked once. - NMethodIterator iter(NMethodIterator::only_not_unloading); - while(iter.next()) { - nmethod* nm = iter.method(); - // Only notify for live nmethods - if (!nm->is_marked_for_deoptimization()) { - for (Dependencies::DepStream deps(nm); deps.next(); ) { - // Construct abstraction of a dependency. - DependencySignature* current_sig = new DependencySignature(deps); - - // Determine if dependency is already checked. table->put(...) returns - // 'true' if the dependency is added (i.e., was not in the hashtable). - if (table->put(*current_sig, 1)) { - if (deps.check_dependency() != nullptr) { - // Dependency checking failed. Print out information about the failed - // dependency and finally fail with an assert. We can fail here, since - // dependency checking is never done in a product build. - tty->print_cr("Failed dependency:"); - changes.print(); - nm->print(); - nm->print_dependencies_on(tty); - assert(false, "Should have been marked for deoptimization"); - } - } - } - } - } -} - bool nmethod::check_dependency_on(DepChange& changes) { // What has happened: // 1) a new class dependee has been added diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 05a00b04aa2..dea88ee6d1c 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -677,10 +677,6 @@ class nmethod : public CompiledMethod { virtual int compile_id() const { return _compile_id; } const char* compile_kind() const; - // tells if any of this method's dependencies have been invalidated - // (this is expensive!) - static void check_all_dependencies(DepChange& changes); - // tells if this compiled method is dependent on the given changes, // and the changes have invalidated it bool check_dependency_on(DepChange& changes); From 0983b54866d7118bb54c87fa3b2260c863376a92 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Thu, 12 Oct 2023 20:02:10 +0000 Subject: [PATCH 013/111] 8318038: ProblemList runtime/CompressedOops/CompressedClassPointers.java on two platforms 8318040: ProblemList vmTestbase/nsk/monitoring/ThreadMXBean/findMonitorDeadlockedThreads/find006/TestDescription.java on macosx-aarch64 8318042: ProblemList java/nio/channels/vthread/BlockingChannelOps.java#direct-register with GenZGC Reviewed-by: rriggs, azvegint --- test/hotspot/jtreg/ProblemList.txt | 4 ++++ test/jdk/ProblemList-generational-zgc.txt | 1 + 2 files changed, 5 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index a76c41f8b38..c81d2825562 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -110,6 +110,8 @@ applications/jcstress/copy.java 8229852 linux-all containers/docker/TestJcmd.java 8278102 linux-all containers/docker/TestMemoryAwareness.java 8303470 linux-all +runtime/CompressedOops/CompressedClassPointers.java 8317610 linux-x64,windows-x64 + ############################################################################# # :hotspot_serviceability @@ -173,3 +175,5 @@ vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_b/TestDescription.java vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494 windows-x64 + +vmTestbase/nsk/monitoring/ThreadMXBean/findMonitorDeadlockedThreads/find006/TestDescription.java 8310144 macosx-aarch64 diff --git a/test/jdk/ProblemList-generational-zgc.txt b/test/jdk/ProblemList-generational-zgc.txt index d6a6f63c6a5..495c9c66f40 100644 --- a/test/jdk/ProblemList-generational-zgc.txt +++ b/test/jdk/ProblemList-generational-zgc.txt @@ -39,3 +39,4 @@ sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java 8307393 generic-all com/sun/jdi/ThreadMemoryLeakTest.java 8307402 generic-all java/util/concurrent/locks/Lock/OOMEInAQS.java 8309218 generic-all +java/nio/channels/vthread/BlockingChannelOps.java#direct-register 8315544 windows-x64 From 77fa44fd4fefbc9ba41a2ed4bd931c326e5255e4 Mon Sep 17 00:00:00 2001 From: ANUPAM DEV Date: Thu, 12 Oct 2023 20:07:07 +0000 Subject: [PATCH 014/111] 8317847: Typo in API documentation of class JPopupMenu Reviewed-by: aivanov --- src/java.desktop/share/classes/javax/swing/JPopupMenu.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java index d21f01f6b12..29cc59b1bb1 100644 --- a/src/java.desktop/share/classes/javax/swing/JPopupMenu.java +++ b/src/java.desktop/share/classes/javax/swing/JPopupMenu.java @@ -934,7 +934,7 @@ public Component getInvoker() { /** * Sets the invoker of this popup menu -- the component in which - * the popup menu menu is to be displayed. + * the popup menu is to be displayed. * * @param invoker the Component in which the popup * menu is displayed From 61ce739ac8453eaa0107241444c35c2f7e9c47dd Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Thu, 12 Oct 2023 22:02:16 +0000 Subject: [PATCH 015/111] 8315484: java/awt/dnd/RejectDragDropActionTest.java timed out Reviewed-by: honkar, aivanov --- .../awt/dnd/RejectDragDropActionTest.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/jdk/java/awt/dnd/RejectDragDropActionTest.java b/test/jdk/java/awt/dnd/RejectDragDropActionTest.java index f8d53ac45bf..9ff3c00ead0 100644 --- a/test/jdk/java/awt/dnd/RejectDragDropActionTest.java +++ b/test/jdk/java/awt/dnd/RejectDragDropActionTest.java @@ -27,10 +27,9 @@ @summary tests that DropTargetDragEvent.getDropAction() returns correct value after DropTargetDragEvent.rejectDrag() @key headful - @run main RejectDragDropActionTest + @run main/timeout=300 RejectDragDropActionTest */ -import java.awt.AWTException; import java.awt.EventQueue; import java.awt.Frame; import java.awt.Point; @@ -46,14 +45,13 @@ import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.InputEvent; -import java.lang.reflect.InvocationTargetException; public class RejectDragDropActionTest { private static volatile boolean incorrectActionDetected = false; - private static final int FRAME_ACTIVATION_TIMEOUT = 3000; + private static final int DELAY_TIME = 500; private static Frame frame; private static DragSource ds; @@ -74,21 +72,23 @@ public void drop(DropTargetDropEvent dtde) { }; private final DropTarget dt = new DropTarget(frame, dtl); - public static void main(String[] args) throws InterruptedException, - InvocationTargetException, AWTException { + public static void main(String[] args) throws Exception { EventQueue.invokeAndWait(() -> { frame = new Frame("RejectDragDropActionTest"); ds = DragSource.getDefaultDragSource(); dgl = dge -> dge.startDrag(null, new StringSelection("OOKK")); - dgr = ds.createDefaultDragGestureRecognizer(frame, DnDConstants.ACTION_COPY, dgl); - frame.setBounds(100, 100, 200, 200); + dgr = ds.createDefaultDragGestureRecognizer(frame, + DnDConstants.ACTION_COPY, dgl); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); frame.setVisible(true); }); try { Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); robot.waitForIdle(); - robot.delay(FRAME_ACTIVATION_TIMEOUT); + robot.delay(DELAY_TIME); Point startPoint = frame.getLocationOnScreen(); Point endPoint = new Point(startPoint); @@ -97,11 +97,11 @@ public static void main(String[] args) throws InterruptedException, robot.mouseMove(startPoint.x, startPoint.y); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - for (Point p = new Point(startPoint); !p.equals(endPoint); + for (Point p = new Point(startPoint); + !p.equals(endPoint) && !incorrectActionDetected; p.translate(sign(endPoint.x - p.x), - sign(endPoint.y - p.y))) { + sign(endPoint.y - p.y))) { robot.mouseMove(p.x, p.y); - robot.delay(50); } robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); From 17535c34bc7853f8e73dfdec2c4da49d78b37bea Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Thu, 12 Oct 2023 22:39:03 +0000 Subject: [PATCH 016/111] 8317818: Combinatorial explosion during 'this' escape analysis Reviewed-by: vromero --- .../tools/javac/comp/ThisEscapeAnalyzer.java | 4 +-- .../tools/javac/warnings/ThisEscape.java | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java index 2dd054619e0..0dd32fd8eca 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java @@ -167,7 +167,7 @@ class ThisEscapeAnalyzer extends TreeScanner { /** Used to terminate recursion in {@link #invokeInvokable invokeInvokable()}. */ - private final Set>> invocations = new HashSet<>(); + private final Set>> invocations = new HashSet<>(); /** Snapshot of {@link #callStack} where a possible 'this' escape occurs. * If non-null, a 'this' escape warning has been found in the current @@ -590,7 +590,7 @@ private void invokeInvokable(JCTree site, List args, return; // Stop infinite recursion here - Pair> invocation = Pair.of(site, refs.clone()); + Pair> invocation = Pair.of(methodInfo.declaration, refs.clone()); if (!invocations.add(invocation)) return; diff --git a/test/langtools/tools/javac/warnings/ThisEscape.java b/test/langtools/tools/javac/warnings/ThisEscape.java index d6ae9f8e8f4..25402c2c547 100644 --- a/test/langtools/tools/javac/warnings/ThisEscape.java +++ b/test/langtools/tools/javac/warnings/ThisEscape.java @@ -617,4 +617,34 @@ public ThisEscapeAssertionError2() { ; } } + + // Verify no infinite recursion loop occurs (JDK-8317818) + public static class ThisEscapeRecursionExplosion { + private Object obj; + public ThisEscapeRecursionExplosion() { + getObject(); + } + private Object getObject() { + if (this.obj == null) { + this.obj = new Object(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + getObject().hashCode(); + } + return this.obj; + } + } } From 993951b85e016475f4cd5079ae21bd5ce1f2830c Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Thu, 12 Oct 2023 23:32:37 +0000 Subject: [PATCH 017/111] 8316464: 3 sun/tools tests ignore VM flags Reviewed-by: sspitsyn, cjplummer --- test/jdk/sun/tools/jcmd/TestProcessHelper.java | 3 ++- test/jdk/sun/tools/jinfo/JInfoTest.java | 12 +++++------- test/jdk/sun/tools/jstat/JStatInterval.java | 7 +++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/test/jdk/sun/tools/jcmd/TestProcessHelper.java b/test/jdk/sun/tools/jcmd/TestProcessHelper.java index 121591fce21..139f21e2d9d 100644 --- a/test/jdk/sun/tools/jcmd/TestProcessHelper.java +++ b/test/jdk/sun/tools/jcmd/TestProcessHelper.java @@ -50,8 +50,9 @@ * @test * @bug 8205654 * @summary Unit test for sun.tools.ProcessHelper class. The test launches Java processes with different Java options - * and checks that sun.tools.ProcessHelper.getMainClass(pid) method returns a correct main class. return a . + * and checks that sun.tools.ProcessHelper.getMainClass(pid) method returns a correct main class. * + * @requires vm.flagless * @requires os.family == "linux" * @modules jdk.jcmd/sun.tools.common:+open * java.base/jdk.internal.classfile diff --git a/test/jdk/sun/tools/jinfo/JInfoTest.java b/test/jdk/sun/tools/jinfo/JInfoTest.java index bea0e4b796c..79512ddf0df 100644 --- a/test/jdk/sun/tools/jinfo/JInfoTest.java +++ b/test/jdk/sun/tools/jinfo/JInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -60,9 +60,8 @@ private static void setFlag() throws Exception { LingeredApp app1 = new JInfoTestLingeredApp(); LingeredApp app2 = new JInfoTestLingeredApp(); try { - String[] params = new String[0];; - LingeredApp.startAppExactJvmOpts(app1, params); - LingeredApp.startAppExactJvmOpts(app2, params); + LingeredApp.startApp(app1); + LingeredApp.startApp(app2); OutputAnalyzer output = jinfo("-flag", "MinHeapFreeRatio=1", "JInfoTestLingeredApp"); output.shouldHaveExitValue(0); output = jinfo("-flag", "MinHeapFreeRatio", "JInfoTestLingeredApp"); @@ -89,9 +88,8 @@ private static void classNameMatch() throws Exception { LingeredApp app1 = new JInfoTestLingeredApp(); LingeredApp app2 = new JInfoTestLingeredApp(); try { - String[] params = new String[0]; - LingeredApp.startAppExactJvmOpts(app1, params); - LingeredApp.startAppExactJvmOpts(app2, params); + LingeredApp.startApp(app1); + LingeredApp.startApp(app2); OutputAnalyzer output = jinfo("JInfoTestLingeredApp"); output.shouldHaveExitValue(0); // "Runtime Environment" written once per proc diff --git a/test/jdk/sun/tools/jstat/JStatInterval.java b/test/jdk/sun/tools/jstat/JStatInterval.java index c3ff9404745..1dfa1f9187b 100644 --- a/test/jdk/sun/tools/jstat/JStatInterval.java +++ b/test/jdk/sun/tools/jstat/JStatInterval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -24,6 +24,7 @@ /** * @test * @bug 8035668 + * @requires vm.flagless * @library /test/lib * @summary Test checks case when target application finishes execution and jstat didn't complete work. jstat is started with interval = 100 (jstat -compiler 100) and monitored application finishes @@ -60,9 +61,7 @@ public static void main(String[] args) { } } public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-cp", - System.getProperty("test.class.path"), + ProcessBuilder pb = ProcessTools.createTestJvm( "-XX:+UsePerfData", Application.class.getName() ); From c88b387881a6e9206f9804b4ca966334c65c008a Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 13 Oct 2023 06:43:42 +0000 Subject: [PATCH 018/111] 8317987: C2 recompilations cause high memory footprint Reviewed-by: adinn, kvn --- src/hotspot/share/opto/c2compiler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index e0ec2e34a0a..2831889a94d 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -118,6 +118,7 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, boo bool do_superword = UseSuperWord; while (!env->failing()) { + ResourceMark rm; // Attempt to compile while subsuming loads into machine instructions. Options options(subsume_loads, do_escape_analysis, From ff0b397e135665fbc763bc4042b95c17f6c5367a Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 13 Oct 2023 06:50:08 +0000 Subject: [PATCH 019/111] 8317959: Check return values of malloc in native java.base coding Reviewed-by: alanb, bpb --- src/java.base/aix/native/libnio/MappedMemoryUtils.c | 10 ++++++++++ src/java.base/unix/native/libjava/java_props_md.c | 12 +++++++++++- src/java.base/windows/native/libjli/cmdtoargs.c | 6 +++++- .../windows/native/libnio/ch/UnixDomainSockets.c | 3 +++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/java.base/aix/native/libnio/MappedMemoryUtils.c b/src/java.base/aix/native/libnio/MappedMemoryUtils.c index 51763e89082..5d0216cc251 100644 --- a/src/java.base/aix/native/libnio/MappedMemoryUtils.c +++ b/src/java.base/aix/native/libnio/MappedMemoryUtils.c @@ -158,6 +158,11 @@ static void check_aix_einval(JNIEnv* env, void* end_address) FILE* proc_file; { char* fname = (char*) malloc(sizeof(char) * PFNAME_LEN); + if (fname == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + return; + } + pid_t the_pid = getpid(); jio_snprintf(fname, PFNAME_LEN, "/proc/%d/map", the_pid); proc_file = fopen(fname, "r"); @@ -170,6 +175,11 @@ static void check_aix_einval(JNIEnv* env, void* end_address) } { prmap_t* map_entry = (prmap_t*) malloc(sizeof(prmap_t)); + if (map_entry == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + fclose(proc_file); + return; + } check_proc_map_array(env, proc_file, map_entry, end_address); free(map_entry); } diff --git a/src/java.base/unix/native/libjava/java_props_md.c b/src/java.base/unix/native/libjava/java_props_md.c index 230de04c079..4766a883472 100644 --- a/src/java.base/unix/native/libjava/java_props_md.c +++ b/src/java.base/unix/native/libjava/java_props_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -238,6 +238,11 @@ static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_s *std_language = "en"; if (language != NULL && mapLookup(language_names, language, std_language) == 0) { *std_language = malloc(strlen(language)+1); + if (*std_language == NULL) { + free(encoding_variant); + JNU_ThrowOutOfMemoryError(env, NULL); + return 0; + } strcpy(*std_language, language); } } @@ -246,6 +251,11 @@ static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_s if (std_country != NULL && country != NULL) { if (mapLookup(country_names, country, std_country) == 0) { *std_country = malloc(strlen(country)+1); + if (*std_country == NULL) { + free(encoding_variant); + JNU_ThrowOutOfMemoryError(env, NULL); + return 0; + } strcpy(*std_country, country); } } diff --git a/src/java.base/windows/native/libjli/cmdtoargs.c b/src/java.base/windows/native/libjli/cmdtoargs.c index 9bbbdaf9865..548e70b9bbf 100644 --- a/src/java.base/windows/native/libjli/cmdtoargs.c +++ b/src/java.base/windows/native/libjli/cmdtoargs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -324,6 +324,10 @@ class Vector { bool check() { // "pgmname" rest of cmdline ie. pgmname + 2 double quotes + space + cmdline from windows char* cptr = (char*) malloc(strlen(argv[0]) + sizeof(char) * 3 + strlen(cmdline) + 1); + if (cptr == NULL) { + printf("*** cannot allocate memory\n"); + doabort(); + } _snprintf(cptr, MAX_PATH, "\"%s\" %s", argv[0], cmdline); JLI_CmdToArgs(cptr); free(cptr); diff --git a/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c index 209c30f3be7..bc185b3aa18 100644 --- a/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c +++ b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c @@ -118,6 +118,9 @@ Java_sun_nio_ch_UnixDomainSockets_init(JNIEnv *env, jclass cl) if (result == SOCKET_ERROR) { if (GetLastError() == WSAENOBUFS) { infoPtr = (LPWSAPROTOCOL_INFOW)malloc(len); + if (infoPtr == NULL) { + return JNI_FALSE; + } result = WSAEnumProtocolsW(0, infoPtr, &len); if (result == SOCKET_ERROR) { free(infoPtr); From ec310fe80971261ab7ee1141c64ffd600e7546c0 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 13 Oct 2023 07:01:50 +0000 Subject: [PATCH 020/111] 8317919: pthread_attr_init handle return value and destroy pthread_attr_t object Reviewed-by: mdoerr, lucy --- src/hotspot/os/aix/os_aix.cpp | 4 +++- src/hotspot/os/linux/os_linux.cpp | 8 +++++++- .../macosx/native/libsplashscreen/splashscreen_sys.m | 4 +++- .../unix/native/libsplashscreen/splashscreen_sys.c | 4 +++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 5a1d05c139c..0a092883fd4 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -769,7 +769,8 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, // Init thread attributes. pthread_attr_t attr; - pthread_attr_init(&attr); + int rslt = pthread_attr_init(&attr); + guarantee(rslt == 0, "pthread_attr_init has to return 0"); guarantee(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0, "???"); // Make sure we run in 1:1 kernel-user-thread mode. @@ -803,6 +804,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, stack_size / K); thread->set_osthread(nullptr); delete osthread; + pthread_attr_destroy(&attr); return false; } diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index afaa5d9778b..40a576c09ae 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -911,7 +911,12 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, // init thread attributes pthread_attr_t attr; - pthread_attr_init(&attr); + int rslt = pthread_attr_init(&attr); + if (rslt != 0) { + thread->set_osthread(nullptr); + delete osthread; + return false; + } pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // Calculate stack size if it's not specified by caller. @@ -960,6 +965,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, stack_size / K); thread->set_osthread(nullptr); delete osthread; + pthread_attr_destroy(&attr); return false; } diff --git a/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m b/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m index 33e850dbb38..66e0c362318 100644 --- a/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m +++ b/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m @@ -273,8 +273,10 @@ static int isInAquaSession() { pthread_attr_t attr; int rc; - pthread_attr_init(&attr); + int rslt = pthread_attr_init(&attr); + if (rslt != 0) return; rc = pthread_create(&thr, &attr, SplashScreenThread, (void *) splash); + pthread_attr_destroy(&attr); } void diff --git a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c index e426ab69c94..c532f1658cb 100644 --- a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c +++ b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c @@ -773,8 +773,10 @@ SplashCreateThread(Splash * splash) { pthread_attr_t attr; int rc; - pthread_attr_init(&attr); + int rslt = pthread_attr_init(&attr); + if (rslt != 0) return; rc = pthread_create(&thr, &attr, SplashScreenThread, (void *) splash); + pthread_attr_destroy(&attr); } void From 1082c0e767a5060d1969edc5ef16f9974e799960 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 13 Oct 2023 07:40:00 +0000 Subject: [PATCH 021/111] 8317677: Specialize Vtablestubs::entry_for() for VtableBlob Reviewed-by: thartmann, kvn --- src/hotspot/share/code/compiledIC.cpp | 13 ++++++------- src/hotspot/share/code/vtableStubs.cpp | 7 +++++++ src/hotspot/share/code/vtableStubs.hpp | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp index c19ee182d51..2127d5e2d26 100644 --- a/src/hotspot/share/code/compiledIC.cpp +++ b/src/hotspot/share/code/compiledIC.cpp @@ -559,15 +559,14 @@ void CompiledIC::compute_monomorphic_entry(const methodHandle& method, bool CompiledIC::is_icholder_entry(address entry) { CodeBlob* cb = CodeCache::find_blob(entry); - if (cb != nullptr && cb->is_adapter_blob()) { - return true; + if (cb == nullptr) { + return false; } - // itable stubs also use CompiledICHolder - if (cb != nullptr && cb->is_vtable_blob()) { - VtableStub* s = VtableStubs::entry_point(entry); - return (s != nullptr) && s->is_itable_stub(); + if (cb->is_adapter_blob()) { + return true; + } else if (cb->is_vtable_blob()) { + return VtableStubs::is_icholder_entry(entry); } - return false; } diff --git a/src/hotspot/share/code/vtableStubs.cpp b/src/hotspot/share/code/vtableStubs.cpp index 934f805eefc..3c07bdba733 100644 --- a/src/hotspot/share/code/vtableStubs.cpp +++ b/src/hotspot/share/code/vtableStubs.cpp @@ -284,6 +284,13 @@ VtableStub* VtableStubs::entry_point(address pc) { return (s == stub) ? s : nullptr; } +bool VtableStubs::is_icholder_entry(address pc) { + assert(contains(pc), "must contain all vtable blobs"); + VtableStub* stub = (VtableStub*)(pc - VtableStub::entry_offset()); + // itable stubs use CompiledICHolder. + return stub->is_itable_stub(); +} + bool VtableStubs::contains(address pc) { // simple solution for now - we may want to use // a faster way if this function is called often diff --git a/src/hotspot/share/code/vtableStubs.hpp b/src/hotspot/share/code/vtableStubs.hpp index 60225d77768..12f81362a51 100644 --- a/src/hotspot/share/code/vtableStubs.hpp +++ b/src/hotspot/share/code/vtableStubs.hpp @@ -106,6 +106,7 @@ class VtableStubs : AllStatic { static address find_itable_stub(int itable_index) { return find_stub(false, itable_index); } static VtableStub* entry_point(address pc); // vtable stub entry point for a pc + static bool is_icholder_entry(address pc); // is the blob containing pc (which must be a vtable blob) an icholder? static bool contains(address pc); // is pc within any stub? static VtableStub* stub_containing(address pc); // stub containing pc or nullptr static int number_of_vtable_stubs() { return _number_of_vtable_stubs; } From 4d9042043ecade75d50c25574a445e6b8ef43618 Mon Sep 17 00:00:00 2001 From: Joachim Kern Date: Fri, 13 Oct 2023 08:29:48 +0000 Subject: [PATCH 022/111] 8315026: ProcessHandle implementation listing processes on AIX should use getprocs64 Reviewed-by: rriggs, stuefe, mbaesken --- .../native/libjava/ProcessHandleImpl_aix.c | 124 +++++++++++++++++- .../native/libjava/ProcessHandleImpl_unix.c | 24 +++- 2 files changed, 139 insertions(+), 9 deletions(-) diff --git a/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c b/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c index 93347bd8c20..3568af24ce4 100644 --- a/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c +++ b/src/java.base/aix/native/libjava/ProcessHandleImpl_aix.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -24,10 +24,12 @@ */ #include "jni.h" +#include "jni_util.h" #include "ProcessHandleImpl_unix.h" #include +#include /* * Implementation of native ProcessHandleImpl functions for AIX. @@ -36,9 +38,127 @@ void os_initNative(JNIEnv *env, jclass clazz) {} +/* + * Return pids of active processes, and optionally parent pids and + * start times for each process. + * For a specific non-zero pid, only the direct children are returned. + * If the pid is zero, all active processes are returned. + * Use getprocs64 to accumulate any process following the rules above. + * The resulting pids are stored into an array of longs named jarray. + * The number of pids is returned if they all fit. + * If the parentArray is non-null, store also the parent pid. + * In this case the parentArray must have the same length as the result pid array. + * Of course in the case of a given non-zero pid all entries in the parentArray + * will contain this pid, so this array does only make sense in the case of a given + * zero pid. + * If the jstimesArray is non-null, store also the start time of the pid. + * In this case the jstimesArray must have the same length as the result pid array. + * If the array(s) (is|are) too short, excess pids are not stored and + * the desired length is returned. + */ jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray, jlongArray jparentArray, jlongArray jstimesArray) { - return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray); + pid_t pid = (pid_t) jpid; + jlong* pids = NULL; + jlong* ppids = NULL; + jlong* stimes = NULL; + jsize parentArraySize = 0; + jsize arraySize = 0; + jsize stimesSize = 0; + jsize count = 0; + + arraySize = (*env)->GetArrayLength(env, jarray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + if (jparentArray != NULL) { + parentArraySize = (*env)->GetArrayLength(env, jparentArray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + + if (arraySize != parentArraySize) { + JNU_ThrowIllegalArgumentException(env, "array sizes not equal"); + return 0; + } + } + if (jstimesArray != NULL) { + stimesSize = (*env)->GetArrayLength(env, jstimesArray); + JNU_CHECK_EXCEPTION_RETURN(env, -1); + + if (arraySize != stimesSize) { + JNU_ThrowIllegalArgumentException(env, "array sizes not equal"); + return 0; + } + } + + const int chunk = 100; + struct procentry64 ProcessBuffer[chunk]; + pid_t idxptr = 0; + int i, num = 0; + + do { // Block to break out of on Exception + pids = (*env)->GetLongArrayElements(env, jarray, NULL); + if (pids == NULL) { + break; + } + if (jparentArray != NULL) { + ppids = (*env)->GetLongArrayElements(env, jparentArray, NULL); + if (ppids == NULL) { + break; + } + } + if (jstimesArray != NULL) { + stimes = (*env)->GetLongArrayElements(env, jstimesArray, NULL); + if (stimes == NULL) { + break; + } + } + + while ((num = getprocs64(ProcessBuffer, sizeof(struct procentry64), NULL, + sizeof(struct fdsinfo64), &idxptr, chunk)) != -1) { + for (i = 0; i < num; i++) { + pid_t childpid = (pid_t) ProcessBuffer[i].pi_pid; + pid_t ppid = (pid_t) ProcessBuffer[i].pi_ppid; + + // Get the parent pid, and start time + if (pid == 0 || ppid == pid) { + if (count < arraySize) { + // Only store if it fits + pids[count] = (jlong) childpid; + + if (ppids != NULL) { + // Store the parentPid + ppids[count] = (jlong) ppid; + } + if (stimes != NULL) { + // Store the process start time + stimes[count] = ((jlong) ProcessBuffer[i].pi_start) * 1000;; + } + } + count++; // Count to tabulate size needed + } + } + if (num < chunk) { + break; + } + } + } while (0); + + if (pids != NULL) { + (*env)->ReleaseLongArrayElements(env, jarray, pids, 0); + } + if (ppids != NULL) { + (*env)->ReleaseLongArrayElements(env, jparentArray, ppids, 0); + } + if (stimes != NULL) { + (*env)->ReleaseLongArrayElements(env, jstimesArray, stimes, 0); + } + + if (num == -1) { + JNU_ThrowByNameWithLastError(env, + "java/lang/RuntimeException", "Unable to retrieve Process info"); + return -1; + } + + // If more pids than array had size for; count will be greater than array size + return count; } pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) { diff --git a/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c b/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c index 56a72fab1db..6c0ea6e67a6 100644 --- a/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c +++ b/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c @@ -488,15 +488,25 @@ void unix_getUserInfo(JNIEnv* env, jobject jinfo, uid_t uid) { * The following functions are common on Solaris, Linux and AIX. */ -#if defined (__linux__) || defined(_AIX) +#if defined (__linux__) /* - * Returns the children of the requested pid and optionally each parent and - * start time. - * Reads /proc and accumulates any process who parent pid matches. - * The resulting pids are stored into the array of longs. + * Return pids of active processes, and optionally parent pids and + * start times for each process. + * For a specific non-zero pid, only the direct children are returned. + * If the pid is zero, all active processes are returned. + * Reads /proc and accumulates any process following the rules above. + * The resulting pids are stored into an array of longs named jarray. * The number of pids is returned if they all fit. - * If the array is too short, the negative of the desired length is returned. + * If the parentArray is non-null, store also the parent pid. + * In this case the parentArray must have the same length as the result pid array. + * Of course in the case of a given non-zero pid all entries in the parentArray + * will contain this pid, so this array does only make sense in the case of a given + * zero pid. + * If the jstimesArray is non-null, store also the start time of the pid. + * In this case the jstimesArray must have the same length as the result pid array. + * If the array(s) (is|are) too short, excess pids are not stored and + * the desired length is returned. */ jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray, jlongArray jparentArray, jlongArray jstimesArray) { @@ -607,7 +617,7 @@ jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray, return count; } -#endif // defined (__linux__) || defined(_AIX) +#endif // defined (__linux__) /* * The following functions are for AIX. From 126f2ace5d36c72a8fced27218a66e0b6f920f85 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 13 Oct 2023 08:53:43 +0000 Subject: [PATCH 023/111] 8318006: remove unused net related coding Reviewed-by: alanb, lucy --- src/java.base/share/native/libnet/net_util.h | 6 -- .../unix/native/libnet/net_util_md.c | 66 ------------------ .../windows/native/libnet/net_util_md.c | 69 ------------------- 3 files changed, 141 deletions(-) diff --git a/src/java.base/share/native/libnet/net_util.h b/src/java.base/share/native/libnet/net_util.h index 771ce3c2bbf..06cf448a01d 100644 --- a/src/java.base/share/native/libnet/net_util.h +++ b/src/java.base/share/native/libnet/net_util.h @@ -170,12 +170,6 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, int len); JNIEXPORT int JNICALL NET_Bind(int fd, SOCKETADDRESS *sa, int len); -JNIEXPORT int JNICALL -NET_MapSocketOption(jint cmd, int *level, int *optname); - -JNIEXPORT int JNICALL -NET_MapSocketOptionV6(jint cmd, int *level, int *optname); - JNIEXPORT jint JNICALL NET_EnableFastTcpLoopback(int fd); diff --git a/src/java.base/unix/native/libnet/net_util_md.c b/src/java.base/unix/native/libnet/net_util_md.c index 67194075c75..8a6249f504f 100644 --- a/src/java.base/unix/native/libnet/net_util_md.c +++ b/src/java.base/unix/native/libnet/net_util_md.c @@ -314,72 +314,6 @@ int NET_IsZeroAddr(jbyte* caddr) { return 1; } -/* - * Map the Java level socket option to the platform specific - * level and option name. - */ -int -NET_MapSocketOption(jint cmd, int *level, int *optname) { - static struct { - jint cmd; - int level; - int optname; - } const opts[] = { - { java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY }, - { java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE }, - { java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER }, - { java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF }, - { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF }, - { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE }, - { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR }, - { java_net_SocketOptions_SO_REUSEPORT, SOL_SOCKET, SO_REUSEPORT }, - { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST }, - { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS }, - { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF }, - { java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF }, - { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP }, - }; - - int i; - - if (ipv6_available()) { - switch (cmd) { - // Different multicast options if IPv6 is enabled - case java_net_SocketOptions_IP_MULTICAST_IF: - case java_net_SocketOptions_IP_MULTICAST_IF2: - *level = IPPROTO_IPV6; - *optname = IPV6_MULTICAST_IF; - return 0; - - case java_net_SocketOptions_IP_MULTICAST_LOOP: - *level = IPPROTO_IPV6; - *optname = IPV6_MULTICAST_LOOP; - return 0; -#if defined(MACOSX) - // Map IP_TOS request to IPV6_TCLASS - case java_net_SocketOptions_IP_TOS: - *level = IPPROTO_IPV6; - *optname = IPV6_TCLASS; - return 0; -#endif - } - } - - /* - * Map the Java level option to the native level - */ - for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) { - if (cmd == opts[i].cmd) { - *level = opts[i].level; - *optname = opts[i].optname; - return 0; - } - } - - /* not found */ - return -1; -} - /* * Wrapper for getsockopt system routine - does any necessary * pre/post processing to deal with OS specific oddities :- diff --git a/src/java.base/windows/native/libnet/net_util_md.c b/src/java.base/windows/native/libnet/net_util_md.c index 4ccc4c6631a..5305a02f1c2 100644 --- a/src/java.base/windows/native/libnet/net_util_md.c +++ b/src/java.base/windows/native/libnet/net_util_md.c @@ -225,75 +225,6 @@ jint reuseport_supported(int ipv6_available) return JNI_FALSE; } -/* call NET_MapSocketOptionV6 for the IPv6 fd only - * and NET_MapSocketOption for the IPv4 fd - */ -JNIEXPORT int JNICALL -NET_MapSocketOptionV6(jint cmd, int *level, int *optname) { - - switch (cmd) { - case java_net_SocketOptions_IP_MULTICAST_IF: - case java_net_SocketOptions_IP_MULTICAST_IF2: - *level = IPPROTO_IPV6; - *optname = IPV6_MULTICAST_IF; - return 0; - - case java_net_SocketOptions_IP_MULTICAST_LOOP: - *level = IPPROTO_IPV6; - *optname = IPV6_MULTICAST_LOOP; - return 0; - } - return NET_MapSocketOption (cmd, level, optname); -} - -/* - * Map the Java level socket option to the platform specific - * level and option name. - */ - -JNIEXPORT int JNICALL -NET_MapSocketOption(jint cmd, int *level, int *optname) { - - typedef struct { - jint cmd; - int level; - int optname; - } sockopts; - - static sockopts opts[] = { - { java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY }, - { java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE }, - { java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER }, - { java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF }, - { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF }, - { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE }, - { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR }, - { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST }, - { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF }, - { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP }, - { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS }, - - }; - - - int i; - - /* - * Map the Java level option to the native level - */ - for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) { - if (cmd == opts[i].cmd) { - *level = opts[i].level; - *optname = opts[i].optname; - return 0; - } - } - - /* not found */ - return -1; -} - - /* * Wrapper for setsockopt dealing with Windows specific issues :- * From e490cf9c650cfd3395e8418de99fbd42fd0d56ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Fri, 13 Oct 2023 11:28:17 +0000 Subject: [PATCH 024/111] 8317432: Async UL: Use memcpy instead of strcpy in Message ctr Reviewed-by: xliu, dholmes --- src/hotspot/share/logging/logAsyncWriter.cpp | 6 ++++-- src/hotspot/share/logging/logAsyncWriter.hpp | 20 +++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/logging/logAsyncWriter.cpp b/src/hotspot/share/logging/logAsyncWriter.cpp index 25292503f3d..178adf22d49 100644 --- a/src/hotspot/share/logging/logAsyncWriter.cpp +++ b/src/hotspot/share/logging/logAsyncWriter.cpp @@ -1,5 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,13 +49,14 @@ const LogDecorations& AsyncLogWriter::None = LogDecorations(LogLevel::Warning, L LogDecorators::None); bool AsyncLogWriter::Buffer::push_back(LogFileStreamOutput* output, const LogDecorations& decorations, const char* msg) { - const size_t sz = Message::calc_size(strlen(msg)); + const size_t len = strlen(msg); + const size_t sz = Message::calc_size(len); const bool is_token = output == nullptr; // Always leave headroom for the flush token. Pushing a token must succeed. const size_t headroom = (!is_token) ? Message::calc_size(0) : 0; if (_pos + sz <= (_capacity - headroom)) { - new(_buf + _pos) Message(output, decorations, msg); + new(_buf + _pos) Message(output, decorations, msg, len); _pos += sz; return true; } diff --git a/src/hotspot/share/logging/logAsyncWriter.hpp b/src/hotspot/share/logging/logAsyncWriter.hpp index 02397f633f7..bd6fcd20a52 100644 --- a/src/hotspot/share/logging/logAsyncWriter.hpp +++ b/src/hotspot/share/logging/logAsyncWriter.hpp @@ -1,5 +1,6 @@ /* * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,13 +67,13 @@ class AsyncLogWriter : public NonJavaThread { uint32_t, 17, /*table_size*/ ALLOC_TYPE, mtLogging>; - // Messsage is the envelop of a log line and its associative data. + // Messsage is the envelope of a log line and its associative data. // Its length is variable because of the zero-terminated c-str. It is only valid when we create it using placement new // within a buffer. // // Example layout: // --------------------------------------------- - // |_output|_decorations|"a log line", |pad| <- pointer aligned. + // |_output|_decorations|"a log line", |pad| <- Message aligned. // |_output|_decorations|"yet another",|pad| // ... // |nullptr|_decorations|"",|pad| <- flush token @@ -84,16 +85,16 @@ class AsyncLogWriter : public NonJavaThread { LogFileStreamOutput* const _output; const LogDecorations _decorations; public: - Message(LogFileStreamOutput* output, const LogDecorations& decorations, const char* msg) + // msglen excludes NUL-byte + Message(LogFileStreamOutput* output, const LogDecorations& decorations, const char* msg, const size_t msglen) : _output(output), _decorations(decorations) { assert(msg != nullptr, "c-str message can not be null!"); - PRAGMA_STRINGOP_OVERFLOW_IGNORED - strcpy(reinterpret_cast(this+1), msg); + memcpy(reinterpret_cast(this+1), msg, msglen + 1); } // Calculate the size for a prospective Message object depending on its message length including the trailing zero static constexpr size_t calc_size(size_t message_len) { - return align_up(sizeof(Message) + message_len + 1, sizeof(void*)); + return align_up(sizeof(Message) + message_len + 1, alignof(Message)); } size_t size() const { @@ -114,6 +115,8 @@ class AsyncLogWriter : public NonJavaThread { public: Buffer(size_t capacity) : _pos(0), _capacity(capacity) { _buf = NEW_C_HEAP_ARRAY(char, capacity, mtLogging); + // Ensure _pos is Message-aligned + _pos = align_up(_buf, alignof(Message)) - _buf; assert(capacity >= Message::calc_size(0), "capcity must be great a token size"); } @@ -124,7 +127,10 @@ class AsyncLogWriter : public NonJavaThread { void push_flush_token(); bool push_back(LogFileStreamOutput* output, const LogDecorations& decorations, const char* msg); - void reset() { _pos = 0; } + void reset() { + // Ensure _pos is Message-aligned + _pos = align_up(_buf, alignof(Message)) - _buf; + } class Iterator { const Buffer& _buf; From 266636deab75a0b30456c18e33c3191a42151ec3 Mon Sep 17 00:00:00 2001 From: Aleksei Voitylov Date: Fri, 13 Oct 2023 11:33:34 +0000 Subject: [PATCH 025/111] 8315940: ARM32: Move field resolution information out of the cpCache Reviewed-by: dsamersoff --- src/hotspot/cpu/arm/interp_masm_arm.cpp | 31 ++ src/hotspot/cpu/arm/interp_masm_arm.hpp | 1 + src/hotspot/cpu/arm/templateTable_arm.cpp | 332 +++++++++++----------- 3 files changed, 205 insertions(+), 159 deletions(-) diff --git a/src/hotspot/cpu/arm/interp_masm_arm.cpp b/src/hotspot/cpu/arm/interp_masm_arm.cpp index 66281326b61..643aea681dd 100644 --- a/src/hotspot/cpu/arm/interp_masm_arm.cpp +++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp @@ -37,6 +37,7 @@ #include "oops/markWord.hpp" #include "oops/method.hpp" #include "oops/methodData.hpp" +#include "oops/resolvedFieldEntry.hpp" #include "oops/resolvedIndyEntry.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" @@ -312,6 +313,36 @@ void InterpreterMacroAssembler::load_resolved_indy_entry(Register cache, Registe add(cache, cache, index); } +void InterpreterMacroAssembler::load_field_entry(Register cache, Register index, int bcp_offset) { + // Get index out of bytecode pointer + assert_different_registers(cache, index); + + get_index_at_bcp(index, bcp_offset, cache /*as tmp*/, sizeof(u2)); + + // Scale the index to be the entry index * sizeof(ResolvedFieldEntry) + // sizeof(ResolvedFieldEntry) is 16 on Arm, so using shift + if (is_power_of_2(sizeof(ResolvedFieldEntry))) { + // load constant pool cache pointer + ldr(cache, Address(FP, frame::interpreter_frame_cache_offset * wordSize)); + // Get address of field entries array + ldr(cache, Address(cache, in_bytes(ConstantPoolCache::field_entries_offset()))); + + add(cache, cache, Array::base_offset_in_bytes()); + add(cache, cache, AsmOperand(index, lsl, log2i_exact(sizeof(ResolvedFieldEntry)))); + } + else { + mov(cache, sizeof(ResolvedFieldEntry)); + mul(index, index, cache); + // load constant pool cache pointer + ldr(cache, Address(FP, frame::interpreter_frame_cache_offset * wordSize)); + + // Get address of field entries array + ldr(cache, Address(cache, in_bytes(ConstantPoolCache::field_entries_offset()))); + add(cache, cache, Array::base_offset_in_bytes()); + add(cache, cache, index); + } +} + // Generate a subtype check: branch to not_subtype if sub_klass is // not a subtype of super_klass. // Profiling code for the subtype check failure (profile_typecheck_failed) diff --git a/src/hotspot/cpu/arm/interp_masm_arm.hpp b/src/hotspot/cpu/arm/interp_masm_arm.hpp index fd0729a0a3b..f02c474f0c0 100644 --- a/src/hotspot/cpu/arm/interp_masm_arm.hpp +++ b/src/hotspot/cpu/arm/interp_masm_arm.hpp @@ -102,6 +102,7 @@ class InterpreterMacroAssembler: public MacroAssembler { void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass); void load_resolved_indy_entry(Register cache, Register index); + void load_field_entry(Register cache, Register index, int bcp_offset = 1); void pop_ptr(Register r); void pop_i(Register r = R0_tos); diff --git a/src/hotspot/cpu/arm/templateTable_arm.cpp b/src/hotspot/cpu/arm/templateTable_arm.cpp index a36188a4337..334e6fb9441 100644 --- a/src/hotspot/cpu/arm/templateTable_arm.cpp +++ b/src/hotspot/cpu/arm/templateTable_arm.cpp @@ -39,6 +39,7 @@ #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/resolvedIndyEntry.hpp" +#include "oops/resolvedFieldEntry.hpp" #include "prims/jvmtiExport.hpp" #include "prims/methodHandles.hpp" #include "runtime/frame.inline.hpp" @@ -227,7 +228,16 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, // additional, required work. assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); assert(load_bc_into_bc_reg, "we use bc_reg as temp"); - __ get_cache_and_index_and_bytecode_at_bcp(bc_reg, temp_reg, temp_reg, byte_no, 1, sizeof(u2)); + __ load_field_entry(temp_reg, bc_reg); + if (byte_no == f1_byte) { + __ add(temp_reg, temp_reg, in_bytes(ResolvedFieldEntry::get_code_offset())); + } else { + __ add(temp_reg, temp_reg, in_bytes(ResolvedFieldEntry::put_code_offset())); + } + // Load-acquire the bytecode to match store-release in ResolvedFieldEntry::fill_in() + __ ldrb(temp_reg, temp_reg); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg, true); + __ mov(bc_reg, bc); __ cbz(temp_reg, L_patch_done); // test if bytecode is zero } @@ -2566,6 +2576,28 @@ void TemplateTable::resolve_cache_and_index(int byte_no, assert_different_registers(Rcache, Rindex, Rtemp); Label resolved; + Bytecodes::Code code = bytecode(); + assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); + __ get_cache_and_index_and_bytecode_at_bcp(Rcache, Rindex, Rtemp, byte_no, 1, index_size); + __ cmp(Rtemp, code); // have we resolved this bytecode? + __ b(resolved, eq); + + // resolve first time through + address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache); + __ mov(R1, code); + __ call_VM(noreg, entry, R1); + // Update registers with resolved info + __ get_cache_and_index_at_bcp(Rcache, Rindex, 1, index_size); + __ bind(resolved); +} + +void TemplateTable::resolve_cache_and_index_for_field(int byte_no, + Register Rcache, + Register Rindex) { + assert_different_registers(Rcache, Rindex, Rtemp); + + Label resolved; + Bytecodes::Code code = bytecode(); switch (code) { case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break; @@ -2574,7 +2606,17 @@ void TemplateTable::resolve_cache_and_index(int byte_no, } assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); - __ get_cache_and_index_and_bytecode_at_bcp(Rcache, Rindex, Rtemp, byte_no, 1, index_size); + __ load_field_entry(Rcache, Rindex); + if (byte_no == f1_byte) { + __ add(Rtemp, Rcache, in_bytes(ResolvedFieldEntry::get_code_offset())); + } else { + __ add(Rtemp, Rcache, in_bytes(ResolvedFieldEntry::put_code_offset())); + } + + // Load-acquire the bytecode to match store-release in ResolvedFieldEntry::fill_in() + __ ldrb(Rtemp, Rtemp); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), noreg, true); + __ cmp(Rtemp, code); // have we resolved this bytecode? __ b(resolved, eq); @@ -2583,10 +2625,35 @@ void TemplateTable::resolve_cache_and_index(int byte_no, __ mov(R1, code); __ call_VM(noreg, entry, R1); // Update registers with resolved info - __ get_cache_and_index_at_bcp(Rcache, Rindex, 1, index_size); + __ load_field_entry(Rcache, Rindex); __ bind(resolved); } +void TemplateTable::load_resolved_field_entry(Register obj, + Register cache, + Register tos_state, + Register offset, + Register flags, + bool is_static = false) { + assert_different_registers(cache, tos_state, flags, offset); + + // Field offset + __ ldr(offset, Address(cache, in_bytes(ResolvedFieldEntry::field_offset_offset()))); + + // Flags + __ ldrb(flags, Address(cache, in_bytes(ResolvedFieldEntry::flags_offset()))); + + // TOS state + __ ldrb(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset()))); + + // Klass overwrite register + if (is_static) { + __ ldr(obj, Address(cache, ResolvedFieldEntry::field_holder_offset())); + const int mirror_offset = in_bytes(Klass::java_mirror_offset()); + __ ldr(obj, Address(obj, mirror_offset)); + __ resolve_oop_handle(obj); + } +} // The Rcache and Rindex registers must be set before call void TemplateTable::load_field_cp_cache_entry(Register Rcache, @@ -2742,8 +2809,8 @@ void TemplateTable::jvmti_post_field_access(Register Rcache, __ cbz(Rtemp, Lcontinue); // cache entry pointer - __ add(R2, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ add(R2, R2, in_bytes(ConstantPoolCache::base_offset())); + __ load_field_entry(R2, Rindex); + if (is_static) { __ mov(R1, 0); // null object reference } else { @@ -2756,7 +2823,7 @@ void TemplateTable::jvmti_post_field_access(Register Rcache, // R2: cache entry pointer __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), R1, R2); - __ get_cache_and_index_at_bcp(Rcache, Rindex, 1); + __ load_field_entry(Rcache, Rindex); __ bind(Lcontinue); } @@ -2773,29 +2840,25 @@ void TemplateTable::pop_and_check_object(Register r) { void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) { transition(vtos, vtos); - const Register Roffset = R2_tmp; - const Register Robj = R3_tmp; - const Register Rcache = R4_tmp; - const Register Rflagsav = Rtmp_save0; // R4/R19 - const Register Rindex = R5_tmp; - const Register Rflags = R5_tmp; + const Register Rcache = R4_tmp; + const Register Rindex = R3_tmp; + + const Register Roffset = R2_tmp; + const Register Rtos_state = R3_tmp; + const Register Robj = R4_tmp; // Rcache is free at the time of loading Robj + const Register Rflags = R5_tmp; - resolve_cache_and_index(byte_no, Rcache, Rindex, sizeof(u2)); + resolve_cache_and_index_for_field(byte_no, Rcache, Rindex); jvmti_post_field_access(Rcache, Rindex, is_static, false); - load_field_cp_cache_entry(Rcache, Rindex, Roffset, Rflags, Robj, is_static); - - __ mov(Rflagsav, Rflags); + load_resolved_field_entry(Robj, Rcache, Rtos_state, Roffset, Rflags, is_static); - if (!is_static) pop_and_check_object(Robj); + if (!is_static) { + pop_and_check_object(Robj); + } Label Done, Lint, Ltable, shouldNotReachHere; Label Lbtos, Lztos, Lctos, Lstos, Litos, Lltos, Lftos, Ldtos, Latos; - // compute type - __ logical_shift_right(Rflags, Rflags, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask flags after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - // There are actually two versions of implementation of getfield/getstatic: // // 1) Table switch using add(PC,...) instruction (fast_version) @@ -2818,16 +2881,16 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr assert(number_of_states == 10, "number of tos states should be equal to 9"); - __ cmp(Rflags, itos); + __ cmp(Rtos_state, itos); if(atos_merged_with_itos) { - __ cmp(Rflags, atos, ne); + __ cmp(Rtos_state, atos, ne); } // table switch by type if(fast_version) { - __ add(PC, PC, AsmOperand(Rflags, lsl, log_max_block_size + Assembler::LogInstructionSize), ne); + __ add(PC, PC, AsmOperand(Rtos_state, lsl, log_max_block_size + Assembler::LogInstructionSize), ne); } else { - __ ldr(PC, Address(PC, Rflags, lsl, LogBytesPerWord), ne); + __ ldr(PC, Address(PC, Rtos_state, lsl, LogBytesPerWord), ne); } // jump to itos/atos case @@ -2868,7 +2931,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr // ztos (same as btos for getfield) { - assert(ztos == seq++, "btos has unexpected value"); + assert(ztos == seq++, "ztos has unexpected value"); FixedSizeCodeBlock ztos_block(_masm, max_block_size, fast_version); __ bind(Lztos); __ access_load_at(T_BOOLEAN, IN_HEAP, Address(Robj, Roffset), R0_tos, noreg, noreg, noreg); @@ -2992,13 +3055,13 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ bind(Done); - // Check for volatile field - Label notVolatile; - __ tbz(Rflagsav, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); - - volatile_barrier(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), Rtemp); - - __ bind(notVolatile); + { + // Check for volatile field + Label notVolatile; + __ tbz(Rflags, ResolvedFieldEntry::is_volatile_shift, notVolatile); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), Rtemp); + __ bind(notVolatile); + } } void TemplateTable::getfield(int byte_no) { @@ -3029,6 +3092,8 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rindex, bool __ ldr_global_s32(Rtemp, (address)JvmtiExport::get_field_modification_count_addr()); __ cbz(Rtemp, Lcontinue); + __ mov(R2, Rcache); + if (is_static) { // Life is simple. Null out the object pointer. __ mov(R1, 0); @@ -3037,16 +3102,10 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rindex, bool // We don't know the size of the value, though; it could be one or two words // depending on its type. As a result, we must find the type to determine where // the object is. + __ ldrb(R3, Address(Rcache, in_bytes(ResolvedFieldEntry::type_offset()))); - __ add(Rtemp, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr_u32(Rtemp, Address(Rtemp, cp_base_offset + ConstantPoolCacheEntry::flags_offset())); - - __ logical_shift_right(Rtemp, Rtemp, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask Rtemp after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - - __ cmp(Rtemp, ltos); - __ cond_cmp(Rtemp, dtos, ne); + __ cmp(R3, ltos); + __ cond_cmp(R3, dtos, ne); // two word value (ltos/dtos) __ ldr(R1, Address(SP, Interpreter::expr_offset_in_bytes(2)), eq); @@ -3054,10 +3113,6 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rindex, bool __ ldr(R1, Address(SP, Interpreter::expr_offset_in_bytes(1)), ne); } - // cache entry pointer - __ add(R2, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ add(R2, R2, in_bytes(cp_base_offset)); - // object (tos) __ mov(R3, Rstack_top); @@ -3066,7 +3121,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rindex, bool // R3: value object on the stack __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), R1, R2, R3); - __ get_cache_and_index_at_bcp(Rcache, Rindex, 1); + __ load_field_entry(Rcache, Rindex); __ bind(Lcontinue); } @@ -3076,34 +3131,29 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rindex, bool void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) { transition(vtos, vtos); - const Register Roffset = R2_tmp; - const Register Robj = R3_tmp; - const Register Rcache = R4_tmp; - const Register Rflagsav = Rtmp_save0; // R4/R19 - const Register Rindex = R5_tmp; - const Register Rflags = R5_tmp; + const Register Rcache = R4_tmp; + const Register Rindex = R3_tmp; + + const Register Roffset = R2_tmp; + const Register Rtos_state = R3_tmp; + const Register Robj = R4_tmp; // Rcache is free at the time of loading Robj + const Register Rflags = R5_tmp; - resolve_cache_and_index(byte_no, Rcache, Rindex, sizeof(u2)); + resolve_cache_and_index_for_field(byte_no, Rcache, Rindex); jvmti_post_field_mod(Rcache, Rindex, is_static); - load_field_cp_cache_entry(Rcache, Rindex, Roffset, Rflags, Robj, is_static); + load_resolved_field_entry(Robj, Rcache, Rtos_state, Roffset, Rflags, is_static); // Check for volatile field - Label notVolatile; - __ mov(Rflagsav, Rflags); - __ tbz(Rflagsav, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); - - volatile_barrier(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp); - - __ bind(notVolatile); + { + Label notVolatile; + __ tbz(Rflags, ResolvedFieldEntry::is_volatile_shift, notVolatile); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp); + __ bind(notVolatile); + } Label Done, Lint, shouldNotReachHere; Label Ltable, Lbtos, Lztos, Lctos, Lstos, Litos, Lltos, Lftos, Ldtos, Latos; - // compute type - __ logical_shift_right(Rflags, Rflags, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask flags after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - // There are actually two versions of implementation of putfield/putstatic: // // 32-bit ARM: @@ -3124,13 +3174,13 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr assert(number_of_states == 10, "number of tos states should be equal to 9"); // itos case is frequent and is moved outside table switch - __ cmp(Rflags, itos); + __ cmp(Rtos_state, itos); // table switch by type if (fast_version) { - __ add(PC, PC, AsmOperand(Rflags, lsl, log_max_block_size + Assembler::LogInstructionSize), ne); + __ add(PC, PC, AsmOperand(Rtos_state, lsl, log_max_block_size + Assembler::LogInstructionSize), ne); } else { - __ ldr(PC, Address(PC, Rflags, lsl, LogBytesPerWord), ne); + __ ldr(PC, Address(PC, Rtos_state, lsl, LogBytesPerWord), ne); } // jump to itos case @@ -3267,7 +3317,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr // atos { - assert(atos == seq++, "dtos has unexpected value"); + assert(atos == seq++, "atos has unexpected value"); __ bind(Latos); __ pop(atos); if (!is_static) pop_and_check_object(Robj); @@ -3293,32 +3343,11 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr __ bind(Done); - Label notVolatile2; - if (is_static) { - // Just check for volatile. Memory barrier for static final field - // is handled by class initialization. - __ tbz(Rflagsav, ConstantPoolCacheEntry::is_volatile_shift, notVolatile2); - volatile_barrier(MacroAssembler::StoreLoad, Rtemp); - __ bind(notVolatile2); - } else { - // Check for volatile field and final field - Label skipMembar; - - __ tst(Rflagsav, 1 << ConstantPoolCacheEntry::is_volatile_shift | - 1 << ConstantPoolCacheEntry::is_final_shift); - __ b(skipMembar, eq); - - __ tbz(Rflagsav, ConstantPoolCacheEntry::is_volatile_shift, notVolatile2); - - // StoreLoad barrier after volatile field write - volatile_barrier(MacroAssembler::StoreLoad, Rtemp); - __ b(skipMembar); - - // StoreStore barrier after final field write - __ bind(notVolatile2); - volatile_barrier(MacroAssembler::StoreStore, Rtemp); - - __ bind(skipMembar); + { + Label notVolatile; + __ tbz(Rflags, ResolvedFieldEntry::is_volatile_shift, notVolatile); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp); + __ bind(notVolatile); } } @@ -3358,7 +3387,7 @@ void TemplateTable::jvmti_post_fast_field_mod(TosState state) { __ push(state); // save value on the stack // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(R2, R1, 1); + __ load_field_entry(R2, R1); __ mov(R1, R3); assert(Interpreter::expr_offset_in_bytes(0) == 0, "adjust this code"); @@ -3383,30 +3412,26 @@ void TemplateTable::fast_storefield(TosState state) { jvmti_post_fast_field_mod(state); - const Register Rcache = R2_tmp; - const Register Rindex = R3_tmp; - const Register Roffset = R3_tmp; - const Register Rflags = Rtmp_save0; // R4/R19 - const Register Robj = R5_tmp; + const Register Rcache = R4_tmp; + const Register Rindex = R3_tmp; - // access constant pool cache - __ get_cache_and_index_at_bcp(Rcache, Rindex, 1); + const Register Roffset = R2_tmp; + const Register Rtos_state = R3_tmp; + const Register Robj = R4_tmp; // Rcache is free at the time of loading Robj + const Register Rflags = R5_tmp; - __ add(Rcache, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord)); + // access constant pool cache + __ load_field_entry(Rcache, Rindex); + load_resolved_field_entry(Robj, Rcache, Rtos_state, Roffset, Rflags); // load flags to test volatile - __ ldr_u32(Rflags, Address(Rcache, base + ConstantPoolCacheEntry::flags_offset())); - - // replace index with field offset from cache entry - __ ldr(Roffset, Address(Rcache, base + ConstantPoolCacheEntry::f2_offset())); - - // Check for volatile store - Label notVolatile; - __ tbz(Rflags, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); - - volatile_barrier(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp); - - __ bind(notVolatile); + { + // Check for volatile store + Label notVolatile; + __ tbz(Rflags, ResolvedFieldEntry::is_volatile_shift, notVolatile); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp); + __ bind(notVolatile); + } // Get object from stack pop_and_check_object(Robj); @@ -3446,23 +3471,14 @@ void TemplateTable::fast_storefield(TosState state) { ShouldNotReachHere(); } - Label notVolatile2; - Label skipMembar; - __ tst(Rflags, 1 << ConstantPoolCacheEntry::is_volatile_shift | - 1 << ConstantPoolCacheEntry::is_final_shift); - __ b(skipMembar, eq); - - __ tbz(Rflags, ConstantPoolCacheEntry::is_volatile_shift, notVolatile2); - - // StoreLoad barrier after volatile field write - volatile_barrier(MacroAssembler::StoreLoad, Rtemp); - __ b(skipMembar); - - // StoreStore barrier after final field write - __ bind(notVolatile2); - volatile_barrier(MacroAssembler::StoreStore, Rtemp); + { + // Check for volatile store + Label notVolatile; + __ tbz(Rflags, ResolvedFieldEntry::is_volatile_shift, notVolatile); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp); + __ bind(notVolatile); + } - __ bind(skipMembar); } void TemplateTable::fast_accessfield(TosState state) { @@ -3476,7 +3492,7 @@ void TemplateTable::fast_accessfield(TosState state) { __ ldr_global_s32(R2, (address) JvmtiExport::get_field_access_count_addr()); __ cbz(R2, done); // access constant pool cache entry - __ get_cache_entry_pointer_at_bcp(R2, R1, 1); + __ load_field_entry(R2, R1); __ push_ptr(R0_tos); // save object pointer before call_VM() clobbers it __ verify_oop(R0_tos); __ mov(R1, R0_tos); @@ -3495,16 +3511,15 @@ void TemplateTable::fast_accessfield(TosState state) { const Register Roffset = R3_tmp; // access constant pool cache - __ get_cache_and_index_at_bcp(Rcache, Rindex, 1); + __ load_field_entry(Rcache, Rindex); // replace index with field offset from cache entry - __ add(Rtemp, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Roffset, Address(Rtemp, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())); + __ ldr(Roffset, Address(Rcache, ResolvedFieldEntry::field_offset_offset())); // load flags to test volatile - __ ldr_u32(Rflags, Address(Rtemp, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); + __ ldrb(Rflags, Address(Rcache, ResolvedFieldEntry::flags_offset())); __ verify_oop(Robj); - __ null_check(Robj, Rtemp); + __ null_check(Robj); Address addr = Address(Robj, Roffset); // access field @@ -3538,13 +3553,13 @@ void TemplateTable::fast_accessfield(TosState state) { ShouldNotReachHere(); } - // Check for volatile load - Label notVolatile; - __ tbz(Rflags, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); - - volatile_barrier(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), Rtemp); - - __ bind(notVolatile); + { + // Check for volatile load + Label notVolatile; + __ tbz(Rflags, ResolvedFieldEntry::is_volatile_shift, notVolatile); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), Rtemp); + __ bind(notVolatile); + } } @@ -3562,12 +3577,11 @@ void TemplateTable::fast_xaccess(TosState state) { __ ldr(Robj, aaddress(0)); // access constant pool cache - __ get_cache_and_index_at_bcp(Rcache, Rindex, 2); - __ add(Rtemp, Rcache, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Roffset, Address(Rtemp, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())); + __ load_field_entry(Rcache, Rindex, 2); + __ ldr(Roffset, Address(Rcache, ResolvedFieldEntry::field_offset_offset())); // load flags to test volatile - __ ldr_u32(Rflags, Address(Rtemp, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); + __ ldrb(Rflags, Address(Rcache, ResolvedFieldEntry::flags_offset())); // make sure exception is reported in correct bcp range (getfield is next instruction) __ add(Rbcp, Rbcp, 1); @@ -3590,13 +3604,13 @@ void TemplateTable::fast_xaccess(TosState state) { ShouldNotReachHere(); } - // Check for volatile load - Label notVolatile; - __ tbz(Rflags, ConstantPoolCacheEntry::is_volatile_shift, notVolatile); - - volatile_barrier(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), Rtemp); - - __ bind(notVolatile); + { + // Check for volatile load + Label notVolatile; + __ tbz(Rflags, ResolvedFieldEntry::is_volatile_shift, notVolatile); + __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), Rtemp); + __ bind(notVolatile); + } __ bind(done); } From 45b7aedabf3ca3d53be6c4bde4fddb584a5accca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Fri, 13 Oct 2023 13:21:34 +0000 Subject: [PATCH 026/111] 8317433: Async UL: Only grab lock once when write():ing Reviewed-by: dholmes, xliu --- src/hotspot/share/logging/logAsyncWriter.cpp | 46 +++++++++----------- src/hotspot/share/logging/logAsyncWriter.hpp | 2 +- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/hotspot/share/logging/logAsyncWriter.cpp b/src/hotspot/share/logging/logAsyncWriter.cpp index 178adf22d49..3d987d04b8d 100644 --- a/src/hotspot/share/logging/logAsyncWriter.cpp +++ b/src/hotspot/share/logging/logAsyncWriter.cpp @@ -116,29 +116,7 @@ AsyncLogWriter::AsyncLogWriter() } } -void AsyncLogWriter::write() { - ResourceMark rm; - AsyncLogMap snapshot; - - // lock protection. This guarantees I/O jobs don't block logsites. - { - AsyncLogLocker locker; - - _buffer_staging->reset(); - swap(_buffer, _buffer_staging); - - // move counters to snapshot and reset them. - _stats.iterate([&] (LogFileStreamOutput* output, uint32_t& counter) { - if (counter > 0) { - bool created = snapshot.put(output, counter); - assert(created == true, "sanity check"); - counter = 0; - } - return true; - }); - _data_available = false; - } - +void AsyncLogWriter::write(AsyncLogMap& snapshot) { int req = 0; auto it = _buffer_staging->iterator(); while (it.hasNext()) { @@ -159,7 +137,7 @@ void AsyncLogWriter::write() { if (counter > 0) { stringStream ss; ss.print(UINT32_FORMAT_W(6) " messages dropped due to async logging", counter); - output->write_blocking(decorations, ss.as_string(false)); + output->write_blocking(decorations, ss.freeze()); } return true; }); @@ -172,15 +150,31 @@ void AsyncLogWriter::write() { void AsyncLogWriter::run() { while (true) { + ResourceMark rm; + AsyncLogMap snapshot; { AsyncLogLocker locker; while (!_data_available) { _lock.wait(0/* no timeout */); } + // Only doing a swap and statistics under the lock to + // guarantee that I/O jobs don't block logsites. + _buffer_staging->reset(); + swap(_buffer, _buffer_staging); + + // move counters to snapshot and reset them. + _stats.iterate([&] (LogFileStreamOutput* output, uint32_t& counter) { + if (counter > 0) { + bool created = snapshot.put(output, counter); + assert(created == true, "sanity check"); + counter = 0; + } + return true; + }); + _data_available = false; } - - write(); + write(snapshot); } } diff --git a/src/hotspot/share/logging/logAsyncWriter.hpp b/src/hotspot/share/logging/logAsyncWriter.hpp index bd6fcd20a52..5015ddfe1a9 100644 --- a/src/hotspot/share/logging/logAsyncWriter.hpp +++ b/src/hotspot/share/logging/logAsyncWriter.hpp @@ -172,7 +172,7 @@ class AsyncLogWriter : public NonJavaThread { AsyncLogWriter(); void enqueue_locked(LogFileStreamOutput* output, const LogDecorations& decorations, const char* msg); - void write(); + void write(AsyncLogMap& snapshot); void run() override; void pre_run() override { NonJavaThread::pre_run(); From 7d31146f4d4ec81728c591d839ee2bb942e5e5fa Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Fri, 13 Oct 2023 13:40:49 +0000 Subject: [PATCH 027/111] 8318028: Remove unused class="centered" from FocusCycle.svg Reviewed-by: serb --- .../share/classes/java/awt/doc-files/FocusCycle.svg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/doc-files/FocusCycle.svg b/src/java.desktop/share/classes/java/awt/doc-files/FocusCycle.svg index 316ea25e7e6..59bd0992c9c 100644 --- a/src/java.desktop/share/classes/java/awt/doc-files/FocusCycle.svg +++ b/src/java.desktop/share/classes/java/awt/doc-files/FocusCycle.svg @@ -1,7 +1,7 @@ """, """ @@ -99,7 +99,7 @@ void html5Output() { """
    """, """ - -
    The overview summary page header.
    @@ -1129,6 +1131,7 @@ void checkModuleDeprecation(boolean found) {

    Module moduletags


    +
    @Deprecated module moduletags
    """, """ @@ -1142,6 +1145,7 @@ void checkModuleAnnotation() {

    Module moduleB


    +
    @AnnotationType(optional="Module Anno\ @@ -1354,11 +1358,13 @@ void checkLinkSource(boolean includePrivate) { checkOutput("moduleA/testpkgmdlA/TestClassInModuleA.html", true, """
    +

    public class TestClassInModuleA extends java.lang.Object
    +
    """); checkOutput("src-html/moduleA/testpkgmdlA/TestClassInModuleA.html", true, """ diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java index 7dd8eaca2a1..9342026b6ca 100644 --- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java +++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -91,7 +91,6 @@ public void test(Path ignore) { -
    """); @@ -100,7 +99,6 @@ public void test(Path ignore) { -
    """); } @@ -120,7 +118,6 @@ public void test1(Path ignore) { -
    """); diff --git a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java index 350ca881b5e..898a498ddee 100644 --- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java +++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java @@ -232,6 +232,7 @@ public void testLinkSource() { """

    DEFAULT_NAME

    +
    static final <\ span class="return-type">java.lang.String DEFAULT_NAME

    name

    +
    java.lang.String&\ nbsp;name
    """); diff --git a/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java b/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java index bf56ec43c1d..b8c2d654aa4 100644 --- a/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java +++ b/test/langtools/jdk/javadoc/doclet/testPackageAnnotation/TestPackageAnnotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -55,6 +55,7 @@ public void testPackageInfoAnnotationNoComment() {

    Package pkg1


    +
    @Deprecated(since="1<2>3") package pkg1
    """); @@ -91,6 +92,7 @@ public void testPackageInfoAndHtml() {

    Package pkg3


    +
    @Deprecated(since="1<2>3") package pkg3
    """); diff --git a/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java b/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java index ceffa141609..5a081250137 100644 --- a/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java +++ b/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -292,6 +292,7 @@ public class X { checkOutput("C.html", true, """
    Some text. Returns the result. More text.
    +
    """); } diff --git a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java index b6f802d8625..08edce2031e 100644 --- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java +++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java @@ -434,8 +434,6 @@ void checkSearchOutput(String fileName, boolean expectedOutput) { """); - checkOutput(fileName, true, - "
    "); } void checkSingleIndex() { diff --git a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java index b4ceac438b2..59649c53d48 100644 --- a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java +++ b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java @@ -138,7 +138,7 @@ public void test(Path base) { .summary-table > div, .details-table > div { text-align:left; padding: 8px 3px 3px 7px; - overflow-x: auto; + overflow: auto hidden; scrollbar-width: thin; }""", "@import url('fonts/dejavu.css');", diff --git a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java index 6b348af9c7a..5cf51b5d4f8 100644 --- a/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSummaryTag/TestSummaryTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -92,9 +92,11 @@ public void test1() { """

    m3

    +
    public void m3()
    First sentence some text maybe second sentence.
    +
    """ ); diff --git a/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java b/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java index 75bef1d4c81..b31fb1df50e 100644 --- a/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java +++ b/test/langtools/jdk/javadoc/doclet/testSystemPropertyPage/TestSystemPropertyPage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -67,11 +67,9 @@ public void test(Path base) throws Exception { checkOutput("system-properties.html", true, """ -
    -

    Mapping C types
    {@code bool}{@link ValueLayout#JAVA_BOOLEAN}{@code boolean}
    {@code char}
    {@code char}
    {@code unsigned char}
    {@link ValueLayout#JAVA_BYTE}{@code byte}
    {@code short}
    {@code short}
    {@code unsigned short}
    {@link ValueLayout#JAVA_SHORT}{@code short}
    {@code int}
    {@code int}
    {@code unsigned int}
    {@link ValueLayout#JAVA_INT}{@code int}
    {@code long}
    {@code long}
    {@code unsigned long}
    {@link ValueLayout#JAVA_LONG}{@code long}
    {@code long long}
    {@code long long}
    {@code unsigned long long}
    {@link ValueLayout#JAVA_LONG}{@code long}
    {@code float}