From 1846a65e32624f6da691c1072f44fcb762b43233 Mon Sep 17 00:00:00 2001 From: Turkhan Badalov Date: Thu, 8 Aug 2024 05:34:32 +0000 Subject: [PATCH 01/84] 8337205: Typo in Stack vs Deque Method table in Deque specification Reviewed-by: liach --- src/java.base/share/classes/java/util/Deque.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/Deque.java b/src/java.base/share/classes/java/util/Deque.java index ce406879894..79e4187a586 100644 --- a/src/java.base/share/classes/java/util/Deque.java +++ b/src/java.base/share/classes/java/util/Deque.java @@ -163,7 +163,7 @@ * * * {@link #peek() peek()} - * {@link #getFirst() getFirst()} + * {@link #peekFirst() peekFirst()} * * * From fa18359007bd80d2e74c07a5a1ea6170e1bd474d Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Thu, 8 Aug 2024 08:55:05 +0000 Subject: [PATCH 02/84] 8335981: ProblemList runtime/Thread/TestAlwaysPreTouchStacks.java for MacOS Reviewed-by: tschatzl --- test/hotspot/jtreg/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index d40a8c2d5f4..2414f3d090a 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -117,8 +117,10 @@ runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le +runtime/Thread/TestAlwaysPreTouchStacks.java 8335167 macosx-aarch64 runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 + applications/jcstress/copy.java 8229852 linux-all containers/docker/TestJcmd.java 8278102 linux-all From a9460a69e74f876274ec64394ac6504580041b21 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Thu, 8 Aug 2024 10:38:02 +0000 Subject: [PATCH 03/84] 8337982: Remove dead undef assrt0n Reviewed-by: stefank, dholmes --- src/hotspot/share/memory/metaspace/blockTree.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hotspot/share/memory/metaspace/blockTree.cpp b/src/hotspot/share/memory/metaspace/blockTree.cpp index 934f25d84cc..1f1e54f4a46 100644 --- a/src/hotspot/share/memory/metaspace/blockTree.cpp +++ b/src/hotspot/share/memory/metaspace/blockTree.cpp @@ -178,8 +178,6 @@ void BlockTree::verify() const { // (which also verifies that we visited every node, or at least // as many nodes as are in this tree) _counter.check(counter); - - #undef assrt0n } void BlockTree::zap_range(MetaWord* p, size_t word_size) { From 3bc4a1acc4bb1885ddba69283b99bbe02f8e43b7 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Thu, 8 Aug 2024 10:40:56 +0000 Subject: [PATCH 04/84] 8233068: HIDPI: Linux: AWT Checkbox check mark is unscaled Reviewed-by: jdv, abhiscxk, honkar --- .../classes/sun/awt/X11/XCheckboxPeer.java | 9 +- .../Checkbox/CheckboxCheckerScalingTest.java | 92 +++++++++++++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java index 88f1784889e..c66cda16443 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XCheckboxPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -362,12 +362,15 @@ public void paintCheckbox(Graphics g, if (armed | selected) { //Paint the check + AffineTransform af = g2.getTransform(); + double scaleX = af.getScaleX(); + double scaleY = af.getScaleY(); // FIXME: is this the right color? g2.setColor(getPeerForeground()); - AffineTransform af = g2.getTransform(); - g2.setTransform(AffineTransform.getTranslateInstance(rx,ry)); + g2.setTransform(AffineTransform.getTranslateInstance(rx * scaleX, ry * scaleY)); + g2.scale(scaleX, scaleY); g2.fill(myCheckMark); g2.setTransform(af); } diff --git a/test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java b/test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java new file mode 100644 index 00000000000..5e531e84801 --- /dev/null +++ b/test/jdk/java/awt/Checkbox/CheckboxCheckerScalingTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Checkbox; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; + +/* + * @test + * @key headful + * @bug 8233068 + * @summary Tests checkbox checker on scaling + * @requires (os.family == "linux") + * @run main CheckboxCheckerScalingTest + */ + +public class CheckboxCheckerScalingTest { + private static Frame frame; + private static Checkbox checkbox; + private static BufferedImage imageAfterChecked; + private static volatile boolean checkmarkFound = false; + + public static void main(String[] args) throws Exception { + System.setProperty("sun.java2d.uiScale", "2"); + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("ComboBox checker scaling test"); + checkbox = new Checkbox("one"); + checkbox.setState(true); + frame.add(checkbox); + frame.pack(); + frame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(100); + EventQueue.invokeAndWait(() -> { + Point point = checkbox.getLocationOnScreen(); + Rectangle rect = new Rectangle(point.x + 5, point.y + 7, 8, 8); + imageAfterChecked = robot.createScreenCapture(rect); + + check: { + for (int i = 0; i < imageAfterChecked.getHeight(); i++) { + for (int j = 0; j < imageAfterChecked.getWidth(); j++) { + if (Color.black.getRGB() == imageAfterChecked.getRGB(i, j)) { + checkmarkFound = true; + break check; + } + } + } + } + }); + + if (!checkmarkFound) { + throw new RuntimeException("Checkmark not scaled"); + } + System.out.println("Test Passed"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} From 088871ce36f85fb30b24c49146f547bc8e2b0dcb Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 8 Aug 2024 10:51:47 +0000 Subject: [PATCH 05/84] 8335267: [XWayland] move screencast tokens from .awt to .java folder Reviewed-by: prr, avu --- .../sun/awt/screencast/TokenStorage.java | 91 +++++++++++-------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java index 3daf9b2a8b8..b05ff7f8c4a 100644 --- a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java +++ b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java @@ -60,35 +60,33 @@ * The restore token allows the ScreenCast session to be restored * with previously granted screen access permissions. */ -@SuppressWarnings("removal") final class TokenStorage { private TokenStorage() {} private static final String REL_NAME = + ".java/robot/screencast-tokens.properties"; + private static final String REL_NAME_SECONDARY = ".awt/robot/screencast-tokens.properties"; private static final Properties PROPS = new Properties(); private static final Path PROPS_PATH; private static final Path PROP_FILENAME; + @SuppressWarnings("removal") private static void doPrivilegedRunnable(Runnable runnable) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - runnable.run(); - return null; - } + AccessController.doPrivileged((PrivilegedAction) () -> { + runnable.run(); + return null; }); } static { - PROPS_PATH = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Path run() { - return setupPath(); - } - }); + @SuppressWarnings("removal") + Path propsPath = AccessController + .doPrivileged((PrivilegedAction) () -> setupPath()); + + PROPS_PATH = propsPath; if (PROPS_PATH != null) { PROP_FILENAME = PROPS_PATH.getFileName(); @@ -110,25 +108,32 @@ private static Path setupPath() { } Path path = Path.of(userHome, REL_NAME); + Path secondaryPath = Path.of(userHome, REL_NAME_SECONDARY); + + boolean copyFromSecondary = !Files.isWritable(path) + && Files.isWritable(secondaryPath); + Path workdir = path.getParent(); - if (!Files.exists(workdir)) { - try { - Files.createDirectories(workdir); - } catch (Exception e) { - if (SCREENCAST_DEBUG) { - System.err.printf("Token storage: cannot create" + - " directory %s %s\n", workdir, e); + if (!Files.isWritable(path)) { + if (!Files.exists(workdir)) { + try { + Files.createDirectories(workdir); + } catch (Exception e) { + if (SCREENCAST_DEBUG) { + System.err.printf("Token storage: cannot create" + + " directory %s %s\n", workdir, e); + } + return null; } - return null; } - } - if (!Files.isWritable(workdir)) { - if (SCREENCAST_DEBUG) { - System.err.printf("Token storage: %s is not writable\n", workdir); + if (!Files.isWritable(workdir)) { + if (SCREENCAST_DEBUG) { + System.err.printf("Token storage: %s is not writable\n", workdir); + } + return null; } - return null; } try { @@ -145,7 +150,17 @@ private static Path setupPath() { } } - if (Files.exists(path)) { + if (copyFromSecondary) { + if (SCREENCAST_DEBUG) { + System.out.println("Token storage: copying from the secondary location " + + secondaryPath); + } + synchronized (PROPS) { + if (readTokens(secondaryPath)) { + store(path, "copy from the secondary location"); + } + } + } else if (Files.exists(path)) { if (!setFilePermission(path)) { return null; } @@ -302,7 +317,7 @@ private static void storeTokenFromNative(String oldToken, } if (changed) { - doPrivilegedRunnable(() -> store("save tokens")); + doPrivilegedRunnable(() -> store(PROPS_PATH, "save tokens")); } } } @@ -315,7 +330,7 @@ private static boolean readTokens(Path path) { PROPS.clear(); PROPS.load(reader); } - } catch (IOException e) { + } catch (IOException | IllegalArgumentException e) { if (SCREENCAST_DEBUG) { System.err.printf(""" Token storage: failed to load property file %s @@ -410,7 +425,7 @@ static Set getTokens(List affectedScreenBounds) { } private static void removeMalformedRecords(Set malformedRecords) { - if (!isWritable() + if (!isWritable(PROPS_PATH) || malformedRecords == null || malformedRecords.isEmpty()) { return; @@ -424,17 +439,17 @@ private static void removeMalformedRecords(Set malformedRecords) { } } - store("remove malformed records"); + store(PROPS_PATH, "remove malformed records"); } } - private static void store(String failMsg) { - if (!isWritable()) { + private static void store(Path path, String failMsg) { + if (!isWritable(path)) { return; } synchronized (PROPS) { - try (BufferedWriter writer = Files.newBufferedWriter(PROPS_PATH)) { + try (BufferedWriter writer = Files.newBufferedWriter(path)) { PROPS.store(writer, null); } catch (IOException e) { if (SCREENCAST_DEBUG) { @@ -445,13 +460,13 @@ private static void store(String failMsg) { } } - private static boolean isWritable() { - if (PROPS_PATH == null - || (Files.exists(PROPS_PATH) && !Files.isWritable(PROPS_PATH))) { + private static boolean isWritable(Path path) { + if (path == null + || (Files.exists(path) && !Files.isWritable(path))) { if (SCREENCAST_DEBUG) { System.err.printf( - "Token storage: %s is not writable\n", PROPS_PATH); + "Token storage: %s is not writable\n", path); } return false; } else { From 12c553f12876b4095685676f800119c0e275bf44 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 8 Aug 2024 10:51:58 +0000 Subject: [PATCH 06/84] 8329471: Remove GTK2 Reviewed-by: abhiscxk, prr, ihse --- .../modules/java.desktop/lib/AwtLibraries.gmk | 4 - .../sun/java/swing/plaf/gtk/GTKEngine.java | 16 +- .../java/swing/plaf/gtk/GTKIconFactory.java | 6 +- .../java/swing/plaf/gtk/GTKLookAndFeel.java | 24 +- .../sun/java/swing/plaf/gtk/GTKPainter.java | 98 +- .../com/sun/java/swing/plaf/gtk/GTKStyle.java | 11 +- .../unix/classes/sun/awt/UNIXToolkit.java | 19 +- .../native/libawt_xawt/awt/gtk2_interface.c | 2603 ----------------- .../native/libawt_xawt/awt/gtk2_interface.h | 448 --- .../native/libawt_xawt/awt/gtk_interface.c | 11 +- .../libawt_xawt/awt/screencast_pipewire.c | 3 +- .../Gtk/GtkVersionTest/GtkVersionTest.java | 7 +- .../ScreenCaptureGtkTest.java | 11 +- .../swing/LookAndFeel/8145547/DemandGTK.java | 3 +- .../swing/LookAndFeel/8145547/DemandGTK2.sh | 91 - .../swing/LookAndFeel/8145547/DemandGTK2.txt | 36 - .../swing/LookAndFeel/8145547/DemandGTK3.sh | 11 +- 17 files changed, 54 insertions(+), 3348 deletions(-) delete mode 100644 src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c delete mode 100644 src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h delete mode 100644 test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh delete mode 100644 test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt diff --git a/make/modules/java.desktop/lib/AwtLibraries.gmk b/make/modules/java.desktop/lib/AwtLibraries.gmk index 11f92585bd9..be29805f352 100644 --- a/make/modules/java.desktop/lib/AwtLibraries.gmk +++ b/make/modules/java.desktop/lib/AwtLibraries.gmk @@ -237,7 +237,6 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) DISABLED_WARNINGS_gcc := int-to-pointer-cast, \ DISABLED_WARNINGS_gcc_awt_Taskbar.c := parentheses, \ DISABLED_WARNINGS_gcc_GLXSurfaceData.c := unused-function, \ - DISABLED_WARNINGS_gcc_gtk2_interface.c := parentheses type-limits, \ DISABLED_WARNINGS_gcc_gtk3_interface.c := parentheses type-limits \ unused-function, \ DISABLED_WARNINGS_gcc_OGLBufImgOps.c := format-nonliteral, \ @@ -252,7 +251,6 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) DISABLED_WARNINGS_gcc_XToolkit.c := unused-result, \ DISABLED_WARNINGS_gcc_XWindow.c := unused-function, \ DISABLED_WARNINGS_clang_awt_Taskbar.c := parentheses, \ - DISABLED_WARNINGS_clang_gtk2_interface.c := parentheses, \ DISABLED_WARNINGS_clang_gtk3_interface.c := parentheses, \ DISABLED_WARNINGS_clang_OGLBufImgOps.c := format-nonliteral, \ DISABLED_WARNINGS_clang_OGLPaints.c := format-nonliteral, \ @@ -262,8 +260,6 @@ ifeq ($(call isTargetOs, windows macosx)+$(ENABLE_HEADLESS_ONLY), false+false) DISABLED_WARNINGS_clang_aix_awt_Taskbar.c := parentheses, \ DISABLED_WARNINGS_clang_aix_OGLPaints.c := format-nonliteral, \ DISABLED_WARNINGS_clang_aix_OGLBufImgOps.c := format-nonliteral, \ - DISABLED_WARNINGS_clang_aix_gtk2_interface.c := parentheses \ - logical-op-parentheses, \ DISABLED_WARNINGS_clang_aix_gtk3_interface.c := parentheses \ logical-op-parentheses, \ DISABLED_WARNINGS_clang_aix_sun_awt_X11_GtkFileDialogPeer.c := \ diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java index 1326cee1403..f9f63076781 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ class GTKEngine { /** Size of the image cache */ private static final int CACHE_SIZE = 50; - /** This enum mirrors that in gtk2_interface.h */ + /** This enum mirrors that in gtk_interface.h */ static enum WidgetType { BUTTON, CHECK_BOX, CHECK_BOX_MENU_ITEM, COLOR_CHOOSER, COMBO_BOX, COMBO_BOX_ARROW_BUTTON, COMBO_BOX_TEXT_FIELD, @@ -493,13 +493,13 @@ public void paintShadow(Graphics g, SynthContext context, GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); int synthState = context.getComponentState(); Container parent = context.getComponent().getParent(); - if(GTKLookAndFeel.is3()) { - if (parent != null && parent.getParent() instanceof JComboBox) { - if (parent.getParent().hasFocus()) { - synthState |= SynthConstants.FOCUSED; - } + + if (parent != null && parent.getParent() instanceof JComboBox) { + if (parent.getParent().hasFocus()) { + synthState |= SynthConstants.FOCUSED; } } + int dir = getTextDirection(context); int widget = getWidgetType(context.getComponent(), id).ordinal(); native_paint_shadow(widget, gtkState, shadowType.ordinal(), detail, @@ -628,7 +628,7 @@ public void themeChanged() { cache.flush(); } - /* GtkSettings enum mirrors that in gtk2_interface.h */ + /* GtkSettings enum mirrors that in gtk_interface.h */ public Object getSetting(Settings property) { synchronized(sun.awt.UNIXToolkit.GTK_LOCK) { return native_get_gtk_setting(property.ordinal()); diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java index 46f8d3ff189..4f04d729099 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ class GTKIconFactory { static final int CHECK_ICON_EXTRA_INSET = 1; static final int DEFAULT_ICON_SPACING = 2; static final int DEFAULT_ICON_SIZE = 13; - static final int DEFAULT_TOGGLE_MENU_ITEM_SIZE = 12; // For pre-gtk2.4 + static final int DEFAULT_TOGGLE_MENU_ITEM_SIZE = 12; private static final String RADIO_BUTTON_ICON = "paintRadioButtonIcon"; private static final String CHECK_BOX_ICON = "paintCheckBoxIcon"; @@ -214,7 +214,7 @@ int getIconDimension(SynthContext context) { Region region = context.getRegion(); GTKStyle style = (GTKStyle) context.getStyle(); - if (GTKLookAndFeel.is3() && region == Region.MENU) { + if (region == Region.MENU) { Object value = style.getClassSpecificValue("arrow-scaling"); if (value instanceof Number) { iconDimension = (int)(((Number) value).floatValue() * diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 93ba22d8dd3..681c0e51958 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -77,7 +77,6 @@ */ @SuppressWarnings("serial") // Superclass not serializable public class GTKLookAndFeel extends SynthLookAndFeel { - private static boolean IS_22; private static boolean IS_3; /** @@ -124,17 +123,6 @@ public class GTKLookAndFeel extends SynthLookAndFeel { */ private static String gtkThemeName = "Default"; - /** - * Returns true if running on system containing at least 2.2. - */ - static boolean is2_2() { - // NOTE: We're currently hard coding to use 2.2. - // If we want to support both GTK 2.0 and 2.2, we'll - // need to get the major/minor/micro version from the .so. - // Refer to bug 4912613 for details. - return IS_22; - } - static boolean is3() { return IS_3; } @@ -1454,17 +1442,7 @@ public void initialize() { throw new InternalError("Unable to load native GTK libraries"); } - if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK2) { - @SuppressWarnings("removal") - String version = AccessController.doPrivileged( - new GetPropertyAction("jdk.gtk.version")); - if (version != null) { - IS_22 = version.equals("2.2"); - } else { - IS_22 = true; - } - } else if (UNIXToolkit.getGtkVersion() == - UNIXToolkit.GtkVersions.GTK3) { + if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK3) { IS_3 = true; } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index 5d77800f88e..4787696a367 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -211,20 +211,7 @@ public void paintRadioButtonMenuItemBackground(SynthContext context, int gtkState = GTKLookAndFeel.synthStateToGTKState( id, context.getComponentState()); if (gtkState == SynthConstants.MOUSE_OVER) { - if (GTKLookAndFeel.is3()) { - paintComponentBackground(context, g, x, y, w, h); - return; - } - synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) { - ShadowType shadow = (GTKLookAndFeel.is2_2() ? - ShadowType.NONE : ShadowType.OUT); - ENGINE.startPainting(g, x, y, w, h, id); - ENGINE.paintBox(g, context, id, gtkState, - shadow, "menuitem", x, y, w, h); - ENGINE.finishPainting(); - } - } + paintComponentBackground(context, g, x, y, w, h); } } @@ -570,21 +557,7 @@ public void paintMenuItemBackground(SynthContext context, int gtkState = GTKLookAndFeel.synthStateToGTKState( context.getRegion(), context.getComponentState()); if (gtkState == SynthConstants.MOUSE_OVER) { - if (GTKLookAndFeel.is3()) { - paintComponentBackground(context, g, x, y, w, h); - return; - } - Region id = Region.MENU_ITEM; - synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) { - ShadowType shadow = (GTKLookAndFeel.is2_2() ? - ShadowType.NONE : ShadowType.OUT); - ENGINE.startPainting(g, x, y, w, h, id); - ENGINE.paintBox(g, context, id, gtkState, shadow, - "menuitem", x, y, w, h); - ENGINE.finishPainting(); - } - } + paintComponentBackground(context, g, x, y, w, h); } } @@ -698,17 +671,14 @@ public void paintSeparatorBackground(SynthContext context, } else { h -= (insets.top + insets.bottom); } - if (GTKLookAndFeel.is3()) { - if (id == Region.POPUP_MENU_SEPARATOR) { - detail = "menuitem"; - h -= (insets.top + insets.bottom); - } else { - detail = "separator"; - } + + if (id == Region.POPUP_MENU_SEPARATOR) { + detail = "menuitem"; + h -= (insets.top + insets.bottom); } else { - detail = orientation == JSeparator.HORIZONTAL ? - "hseparator" : "vseparator"; + detail = "separator"; } + synchronized (UNIXToolkit.GTK_LOCK) { if (! ENGINE.paintCachedImage(g, x, y, w, h, id, state, detail, orientation)) { @@ -823,15 +793,15 @@ public void paintSliderTrackBackground(SynthContext context, // The ubuntulooks engine paints slider troughs differently depending // on the current slider value and its component orientation. JSlider slider = (JSlider)context.getComponent(); - if (GTKLookAndFeel.is3()) { - if (slider.getOrientation() == JSlider.VERTICAL) { - y += 1; - h -= 2; - } else { - x += 1; - w -= 2; - } + + if (slider.getOrientation() == JSlider.VERTICAL) { + y += 1; + h -= 2; + } else { + x += 1; + w -= 2; } + double value = slider.getValue(); double min = slider.getMinimum(); double max = slider.getMaximum(); @@ -865,7 +835,7 @@ public void paintSliderThumbBackground(SynthContext context, Region id = context.getRegion(); int gtkState = GTKLookAndFeel.synthStateToGTKState( id, context.getComponentState()); - boolean hasFocus = GTKLookAndFeel.is3() && + boolean hasFocus = ((context.getComponentState() & SynthConstants.FOCUSED) != 0); synchronized (UNIXToolkit.GTK_LOCK) { if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir, @@ -1059,21 +1029,10 @@ private void paintTextBackground(SynthContext context, Graphics g, int yThickness = style.getYThickness(); ENGINE.startPainting(g, x, y, w, h, id, state); - if (GTKLookAndFeel.is3()) { - ENGINE.paintBackground(g, context, id, gtkState, null, - x, y, w, h); - } + ENGINE.paintBackground(g, context, id, gtkState, null, + x, y, w, h); ENGINE.paintShadow(g, context, id, gtkState, ShadowType.IN, "entry", x, y, w, h); - if (!GTKLookAndFeel.is3()) { - ENGINE.paintFlatBox(g, context, id, - gtkState, ShadowType.NONE, "entry_bg", - x + xThickness, - y + yThickness, - w - (2 * xThickness), - h - (2 * yThickness), - ColorType.TEXT_BACKGROUND); - } if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) { if (!interiorFocus) { @@ -1084,14 +1043,14 @@ private void paintTextBackground(SynthContext context, Graphics g, } else { if (containerParent instanceof JComboBox) { x += (focusSize + 2); - y += focusSize + (GTKLookAndFeel.is3() ? 3 : 1); - w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 1); - h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 6 : 2); + y += focusSize + 3; + w -= 2 * focusSize + 4; + h -= 2 * focusSize + 6; } else { - x += focusSize + (GTKLookAndFeel.is3() ? 2 : 0); - y += focusSize + (GTKLookAndFeel.is3() ? 2 :0 ); - w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); - h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0); + x += focusSize + 2; + y += focusSize + 2; + w -= 2 * focusSize + 4; + h -= 2 * focusSize + 4; } } ENGINE.paintFocus(g, context, id, gtkState, @@ -1437,11 +1396,6 @@ public void paintMenuArrowIcon(SynthContext context, Graphics g, if (gtkState == SynthConstants.MOUSE_OVER) { shadow = ShadowType.IN; } - if (!GTKLookAndFeel.is3()) { - x += 3; - y += 3; - w = h = 7; - } ENGINE.paintArrow(g, context, Region.MENU_ITEM, gtkState, shadow, dir, "menuitem", x, y, w, h); } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java index 3ba534ea2a7..90c05135368 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java @@ -751,14 +751,7 @@ public boolean isOpaque(SynthContext context) { region == Region.EDITOR_PANE) { return true; } - if (!GTKLookAndFeel.is3()) { - if (region == Region.FORMATTED_TEXT_FIELD || - region == Region.PASSWORD_FIELD || - region == Region.SPINNER || - region == Region.TEXT_FIELD) { - return true; - } - } + Component c = context.getComponent(); String name = c.getName(); if (name == "ComboBox.renderer" || name == "ComboBox.listRenderer") { @@ -884,7 +877,7 @@ else if ("CheckBox.iconTextGap".equals(key) || int focusPad = getClassSpecificIntValue(context, "focus-padding", 1); return indicatorSpacing + focusSize + focusPad; - } else if (GTKLookAndFeel.is3() && "ComboBox.forceOpaque".equals(key)) { + } else if ("ComboBox.forceOpaque".equals(key)) { return true; } else if ("Tree.expanderSize".equals(key)) { Object value = getClassSpecificValue("expander-size"); diff --git a/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java b/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java index 191a12092a1..d509fe802b0 100644 --- a/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java @@ -70,19 +70,12 @@ public abstract class UNIXToolkit extends SunToolkit private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 }; private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000; - private static final String GTK2_DEPRECATION_MESSAGE = - "WARNING: the GTK 2 library is deprecated and " + - "its support will be removed in a future release"; - private static volatile boolean gtk2WarningIssued = false; - // Allowed GTK versions public enum GtkVersions { ANY(0), - GTK2(Constants.GTK2_MAJOR_NUMBER), GTK3(Constants.GTK3_MAJOR_NUMBER); static class Constants { - static final int GTK2_MAJOR_NUMBER = 2; static final int GTK3_MAJOR_NUMBER = 3; } @@ -94,8 +87,6 @@ static class Constants { public static GtkVersions getVersion(int number) { switch (number) { - case Constants.GTK2_MAJOR_NUMBER: - return GTK2; case Constants.GTK3_MAJOR_NUMBER: return GTK3; default: @@ -498,15 +489,7 @@ public static GtkVersions getEnabledGtkVersion() { @SuppressWarnings("removal") String version = AccessController.doPrivileged( new GetPropertyAction("jdk.gtk.version")); - if (version == null) { - return GtkVersions.ANY; - } else if (version.startsWith("2")) { - if (!gtk2WarningIssued) { - System.err.println(GTK2_DEPRECATION_MESSAGE); - gtk2WarningIssued = true; - } - return GtkVersions.GTK2; - } else if("3".equals(version) ){ + if ("3".equals(version)) { return GtkVersions.GTK3; } return GtkVersions.ANY; diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c deleted file mode 100644 index 7dba83e9024..00000000000 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ /dev/null @@ -1,2603 +0,0 @@ -/* - * 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 - * 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. - */ - -#ifdef HEADLESS - #error This file should not be included in headless library -#endif - -#include -#include -#include -#include -#include -#include -#include "gtk2_interface.h" -#include "java_awt_Transparency.h" -#include "jvm_md.h" -#include "sizecalc.h" -#include -#include "awt.h" - -#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)()) - -#define G_TYPE_FUNDAMENTAL_SHIFT (2) -#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) - -#define CONV_BUFFER_SIZE 128 - -#define NO_SYMBOL_EXCEPTION 1 - -static void *gtk2_libhandle = NULL; -static void *gthread_libhandle = NULL; - -static jmp_buf j; - -/* Widgets */ -static GtkWidget *gtk2_widget = NULL; -static GtkWidget *gtk2_window = NULL; -static GtkFixed *gtk2_fixed = NULL; - -/* Paint system */ -static GdkPixmap *gtk2_white_pixmap = NULL; -static GdkPixmap *gtk2_black_pixmap = NULL; -static GdkPixbuf *gtk2_white_pixbuf = NULL; -static GdkPixbuf *gtk2_black_pixbuf = NULL; -static int gtk2_pixbuf_width = 0; -static int gtk2_pixbuf_height = 0; - -/* Static buffer for conversion from java.lang.String to UTF-8 */ -static char convertionBuffer[CONV_BUFFER_SIZE]; - -static gboolean new_combo = TRUE; -const char ENV_PREFIX[] = "GTK_MODULES="; - - -static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE]; - -/************************* - * Glib function pointers - *************************/ - -static gboolean (*fp_g_main_context_iteration)(GMainContext *context, - gboolean may_block); - -static GValue* (*fp_g_value_init)(GValue *value, GType g_type); -static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type); -static gboolean (*fp_g_value_get_boolean)(const GValue *value); -static gchar (*fp_g_value_get_char)(const GValue *value); -static guchar (*fp_g_value_get_uchar)(const GValue *value); -static gint (*fp_g_value_get_int)(const GValue *value); -static guint (*fp_g_value_get_uint)(const GValue *value); -static glong (*fp_g_value_get_long)(const GValue *value); -static gulong (*fp_g_value_get_ulong)(const GValue *value); -static gint64 (*fp_g_value_get_int64)(const GValue *value); -static guint64 (*fp_g_value_get_uint64)(const GValue *value); -static gfloat (*fp_g_value_get_float)(const GValue *value); -static gdouble (*fp_g_value_get_double)(const GValue *value); -static const gchar* (*fp_g_value_get_string)(const GValue *value); -static gint (*fp_g_value_get_enum)(const GValue *value); -static guint (*fp_g_value_get_flags)(const GValue *value); -static GParamSpec* (*fp_g_value_get_param)(const GValue *value); -static gpointer* (*fp_g_value_get_boxed)(const GValue *value); -static gpointer* (*fp_g_value_get_pointer)(const GValue *value); -static GObject* (*fp_g_value_get_object)(const GValue *value); -static GParamSpec* (*fp_g_param_spec_int)(const gchar *name, - const gchar *nick, const gchar *blurb, - gint minimum, gint maximum, gint default_value, - GParamFlags flags); -static void (*fp_g_object_get)(gpointer object, - const gchar* fpn, ...); -static void (*fp_g_object_set)(gpointer object, - const gchar *first_property_name, - ...); -/************************ - * GDK function pointers - ************************/ -static GdkPixmap *(*fp_gdk_pixmap_new)(GdkDrawable *drawable, - gint width, gint height, gint depth); -static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*); -static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32); -static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean, - gint, gint, gint, gint); -static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace, - gboolean has_alpha, int bits_per_sample, int width, int height); -static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable, - gint* width, gint* height); - -/************************ - * Gtk function pointers - ************************/ -static gboolean (*fp_gtk_init_check)(int* argc, char** argv); - -/* Painting */ -static void (*fp_gtk_paint_hline)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint x1, gint x2, gint y); -static void (*fp_gtk_paint_vline)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint y1, gint y2, gint x); -static void (*fp_gtk_paint_shadow)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_arrow)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - GtkArrowType arrow_type, gboolean fill, gint x, gint y, - gint width, gint height); -static void (*fp_gtk_paint_box)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_flat_box)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_check)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_option)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_box_gap)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, - GtkPositionType gap_side, gint gap_x, gint gap_width); -static void (*fp_gtk_paint_extension)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, GtkPositionType gap_side); -static void (*fp_gtk_paint_focus)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint x, gint y, gint width, gint height); -static void (*fp_gtk_paint_slider)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -static void (*fp_gtk_paint_handle)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GtkShadowType shadow_type, - GdkRectangle* area, GtkWidget* widget, const gchar* detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation); -static void (*fp_gtk_paint_expander)(GtkStyle* style, GdkWindow* window, - GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, - const gchar* detail, gint x, gint y, GtkExpanderStyle expander_style); -static void (*fp_gtk_style_apply_default_background)(GtkStyle* style, - GdkWindow* window, gboolean set_bg, GtkStateType state_type, - GdkRectangle* area, gint x, gint y, gint width, gint height); - -/* Widget creation */ -static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type, - GtkShadowType shadow_type); -static GtkWidget* (*fp_gtk_button_new)(); -static GtkWidget* (*fp_gtk_check_button_new)(); -static GtkWidget* (*fp_gtk_check_menu_item_new)(); -static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title); -static GtkWidget* (*fp_gtk_combo_box_new)(); -static GtkWidget* (*fp_gtk_combo_box_entry_new)(); -static GtkWidget* (*fp_gtk_entry_new)(); -static GtkWidget* (*fp_gtk_fixed_new)(); -static GtkWidget* (*fp_gtk_handle_box_new)(); -static GtkWidget* (*fp_gtk_hpaned_new)(); -static GtkWidget* (*fp_gtk_vpaned_new)(); -static GtkWidget* (*fp_gtk_hscale_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_vscale_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment); -static GtkWidget* (*fp_gtk_hseparator_new)(); -static GtkWidget* (*fp_gtk_vseparator_new)(); -static GtkWidget* (*fp_gtk_image_new)(); -static GtkWidget* (*fp_gtk_label_new)(const gchar* str); -static GtkWidget* (*fp_gtk_menu_new)(); -static GtkWidget* (*fp_gtk_menu_bar_new)(); -static GtkWidget* (*fp_gtk_menu_item_new)(); -static GtkWidget* (*fp_gtk_notebook_new)(); -static GtkWidget* (*fp_gtk_progress_bar_new)(); -static GtkWidget* (*fp_gtk_progress_bar_set_orientation)( - GtkProgressBar *pbar, - GtkProgressBarOrientation orientation); -static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group); -static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group); -static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -static GtkWidget* (*fp_gtk_separator_menu_item_new)(); -static GtkWidget* (*fp_gtk_separator_tool_item_new)(); -static GtkWidget* (*fp_gtk_text_view_new)(); -static GtkWidget* (*fp_gtk_toggle_button_new)(); -static GtkWidget* (*fp_gtk_toolbar_new)(); -static GtkWidget* (*fp_gtk_tree_view_new)(); -static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment, - GtkAdjustment *vadjustment); -static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type); -static GtkWidget* (*fp_gtk_dialog_new)(); -static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment, - gdouble climb_rate, guint digits); -static GtkWidget* (*fp_gtk_frame_new)(const gchar *label); - -/* Other widget operations */ -static GtkObject* (*fp_gtk_adjustment_new)(gdouble value, - gdouble lower, gdouble upper, gdouble step_increment, - gdouble page_increment, gdouble page_size); -static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget); -static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell, - GtkWidget *child); -static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, - GtkWidget *submenu); -static void (*fp_gtk_widget_realize)(GtkWidget *widget); -static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget, - const gchar *stock_id, GtkIconSize size, const gchar *detail); -static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name); -static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent); -static void (*fp_gtk_widget_set_direction)(GtkWidget *widget, - GtkTextDirection direction); -static void (*fp_gtk_widget_style_get)(GtkWidget *widget, - const gchar *first_property_name, ...); -static void (*fp_gtk_widget_class_install_style_property)( - GtkWidgetClass* class, GParamSpec *pspec); -static GParamSpec* (*fp_gtk_widget_class_find_style_property)( - GtkWidgetClass* class, const gchar* property_name); -static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget, - const gchar* property_name, GValue* value); -static char* (*fp_pango_font_description_to_string)( - const PangoFontDescription* fd); -static GtkSettings* (*fp_gtk_settings_get_default)(); -static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget); -static GType (*fp_gtk_border_get_type)(); -static void (*fp_gtk_arrow_set)(GtkWidget* arrow, - GtkArrowType arrow_type, - GtkShadowType shadow_type); -static void (*fp_gtk_widget_size_request)(GtkWidget *widget, - GtkRequisition *requisition); -static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range); - -/* Method bodies */ - -static void throw_exception(JNIEnv *env, const char* name, const char* message) -{ - jclass class = (*env)->FindClass(env, name); - - if (class != NULL) - (*env)->ThrowNew(env, class, message); - - (*env)->DeleteLocalRef(env, class); -} - -/* This is a workaround for the bug: - * http://sourceware.org/bugzilla/show_bug.cgi?id=1814 - * (dlsym/dlopen clears dlerror state) - * This bug is specific to Linux, but there is no harm in - * applying this workaround on Solaris as well. - */ -static void* dl_symbol(const char* name) -{ - void* result = dlsym(gtk2_libhandle, name); - if (!result) - longjmp(j, NO_SYMBOL_EXCEPTION); - - return result; -} - -static void* dl_symbol_gthread(const char* name) -{ - void* result = dlsym(gthread_libhandle, name); - if (!result) - longjmp(j, NO_SYMBOL_EXCEPTION); - - return result; -} - -gboolean gtk2_check(const char* lib_name, gboolean load) -{ - if (gtk2_libhandle != NULL) { - /* We've already successfully opened the GTK libs, so return true. */ - return TRUE; - } else { - void *lib = NULL; - -#ifdef RTLD_NOLOAD - /* Just check if gtk libs are already in the process space */ - lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD); - if (!load || lib != NULL) { - return lib != NULL; - } -#else -#ifdef _AIX - /* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */ - /* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */ - /* probably not worth it because most AIX servers don't have GTK libs anyway */ -#endif -#endif - - lib = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); - if (lib == NULL) { - return FALSE; - } - - fp_gtk_check_version = dlsym(lib, "gtk_check_version"); - /* Check for GTK 2.2+ */ - if (!fp_gtk_check_version(2, 2, 0)) { - return TRUE; - } - - // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065 - // dlclose(lib); - - return FALSE; - } -} - -#define ADD_SUPPORTED_ACTION(actionStr) \ -do { \ - jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \ - if (!(*env)->ExceptionCheck(env)) { \ - jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \ - (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \ - } else { \ - (*env)->ExceptionClear(env); \ - } \ -} while(0); - - -static void update_supported_actions(JNIEnv *env) { - GVfs * (*fp_g_vfs_get_default) (void); - const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); - const gchar * const * schemes = NULL; - - jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action"); - CHECK_NULL(cls_action); - jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer"); - CHECK_NULL(cls_xDesktopPeer); - jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;"); - CHECK_NULL(fld_supportedActions); - jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions); - - jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList"); - CHECK_NULL(cls_arrayList); - jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z"); - CHECK_NULL(mid_arrayListAdd); - jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V"); - CHECK_NULL(mid_arrayListClear); - - (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear); - - ADD_SUPPORTED_ACTION("OPEN"); - - /** - * gtk_show_uri() documentation says: - * - * > you need to install gvfs to get support for uri schemes such as http:// - * > or ftp://, as only local files are handled by GIO itself. - * - * So OPEN action was safely added here. - * However, it looks like Solaris 11 have gvfs support only for 32-bit - * applications only by default. - */ - - fp_g_vfs_get_default = dl_symbol("g_vfs_get_default"); - fp_g_vfs_get_supported_uri_schemes = dl_symbol("g_vfs_get_supported_uri_schemes"); - dlerror(); - - if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) { - GVfs * vfs = fp_g_vfs_get_default(); - schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL; - if (schemes) { - int i = 0; - while (schemes[i]) { - if (strcmp(schemes[i], "http") == 0) { - ADD_SUPPORTED_ACTION("BROWSE"); - ADD_SUPPORTED_ACTION("MAIL"); - break; - } - i++; - } - } - } else { -#ifdef DEBUG - fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n"); -#endif /* DEBUG */ - } - -} -/** - * Functions for awt_Desktop.c - */ -static gboolean gtk2_show_uri_load(JNIEnv *env) { - gboolean success = FALSE; - dlerror(); - const char *gtk_version = fp_gtk_check_version(2, 14, 0); - if (gtk_version != NULL) { - // The gtk_show_uri is available from GTK+ 2.14 -#ifdef DEBUG - fprintf (stderr, "The version of GTK is %s. " - "The gtk_show_uri function is supported " - "since GTK+ 2.14.\n", gtk_version); -#endif /* DEBUG */ - } else { - // Loading symbols only if the GTK version is 2.14 and higher - fp_gtk_show_uri = dl_symbol("gtk_show_uri"); - const char *dlsym_error = dlerror(); - if (dlsym_error) { -#ifdef DEBUG - fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error); -#endif /* DEBUG */ - } else if (fp_gtk_show_uri == NULL) { -#ifdef DEBUG - fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); -#endif /* DEBUG */ - } else { - gtk->gtk_show_uri = fp_gtk_show_uri; - update_supported_actions(env); - success = TRUE; - } - } - return success; -} - -/** - * Functions for sun_awt_X11_GtkFileDialogPeer.c - */ -static void gtk2_file_chooser_load() -{ - fp_gtk_file_chooser_get_filename = dl_symbol( - "gtk_file_chooser_get_filename"); - fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new"); - fp_gtk_file_chooser_set_current_folder = dl_symbol( - "gtk_file_chooser_set_current_folder"); - fp_gtk_file_chooser_set_filename = dl_symbol( - "gtk_file_chooser_set_filename"); - fp_gtk_file_chooser_set_current_name = dl_symbol( - "gtk_file_chooser_set_current_name"); - fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom"); - fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter"); - fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type"); - fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new"); - if (fp_gtk_check_version(2, 8, 0) == NULL) { - fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol( - "gtk_file_chooser_set_do_overwrite_confirmation"); - } - fp_gtk_file_chooser_set_select_multiple = dl_symbol( - "gtk_file_chooser_set_select_multiple"); - fp_gtk_file_chooser_get_current_folder = dl_symbol( - "gtk_file_chooser_get_current_folder"); - fp_gtk_file_chooser_get_filenames = dl_symbol( - "gtk_file_chooser_get_filenames"); - fp_gtk_g_slist_length = dl_symbol("g_slist_length"); - fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid"); -} - -GtkApi* gtk2_load(JNIEnv *env, const char* lib_name) -{ - gboolean result; - int i; - int (*handler)(); - int (*io_handler)(); - char *gtk_modules_env; - - gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); - if (gtk2_libhandle == NULL) { - return FALSE; - } - - gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); - if (gthread_libhandle == NULL) { - gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL); - if (gthread_libhandle == NULL) - return FALSE; - } - - if (setjmp(j) == 0) - { - fp_gtk_check_version = dl_symbol("gtk_check_version"); - /* Check for GTK 2.2+ */ - if (fp_gtk_check_version(2, 2, 0)) { - longjmp(j, NO_SYMBOL_EXCEPTION); - } - - /* GLib */ - fp_glib_check_version = dlsym(gtk2_libhandle, "glib_check_version"); - if (!fp_glib_check_version) { - dlerror(); - } - fp_g_free = dl_symbol("g_free"); - fp_g_object_unref = dl_symbol("g_object_unref"); - - fp_g_main_context_iteration = - dl_symbol("g_main_context_iteration"); - - fp_g_value_init = dl_symbol("g_value_init"); - fp_g_type_is_a = dl_symbol("g_type_is_a"); - - fp_g_value_get_boolean = dl_symbol("g_value_get_boolean"); - fp_g_value_get_char = dl_symbol("g_value_get_char"); - fp_g_value_get_uchar = dl_symbol("g_value_get_uchar"); - fp_g_value_get_int = dl_symbol("g_value_get_int"); - fp_g_value_get_uint = dl_symbol("g_value_get_uint"); - fp_g_value_get_long = dl_symbol("g_value_get_long"); - fp_g_value_get_ulong = dl_symbol("g_value_get_ulong"); - fp_g_value_get_int64 = dl_symbol("g_value_get_int64"); - fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64"); - fp_g_value_get_float = dl_symbol("g_value_get_float"); - fp_g_value_get_double = dl_symbol("g_value_get_double"); - fp_g_value_get_string = dl_symbol("g_value_get_string"); - fp_g_value_get_enum = dl_symbol("g_value_get_enum"); - fp_g_value_get_flags = dl_symbol("g_value_get_flags"); - fp_g_value_get_param = dl_symbol("g_value_get_param"); - fp_g_value_get_boxed = dl_symbol("g_value_get_boxed"); - fp_g_value_get_pointer = dl_symbol("g_value_get_pointer"); - fp_g_value_get_object = dl_symbol("g_value_get_object"); - fp_g_param_spec_int = dl_symbol("g_param_spec_int"); - fp_g_object_get = dl_symbol("g_object_get"); - fp_g_object_set = dl_symbol("g_object_set"); - - /* GDK */ - fp_gdk_get_default_root_window = - dl_symbol("gdk_get_default_root_window"); - fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new"); - fp_gdk_pixbuf_get_from_drawable = - dl_symbol("gdk_pixbuf_get_from_drawable"); - fp_gdk_pixbuf_scale_simple = - dl_symbol("gdk_pixbuf_scale_simple"); - fp_gdk_gc_new = dl_symbol("gdk_gc_new"); - fp_gdk_rgb_gc_set_foreground = - dl_symbol("gdk_rgb_gc_set_foreground"); - fp_gdk_draw_rectangle = dl_symbol("gdk_draw_rectangle"); - fp_gdk_drawable_get_size = dl_symbol("gdk_drawable_get_size"); - - /* Pixbuf */ - fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new"); - fp_gdk_pixbuf_new_from_file = - dl_symbol("gdk_pixbuf_new_from_file"); - fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width"); - fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height"); - fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels"); - fp_gdk_pixbuf_get_rowstride = - dl_symbol("gdk_pixbuf_get_rowstride"); - fp_gdk_pixbuf_get_has_alpha = - dl_symbol("gdk_pixbuf_get_has_alpha"); - fp_gdk_pixbuf_get_bits_per_sample = - dl_symbol("gdk_pixbuf_get_bits_per_sample"); - fp_gdk_pixbuf_get_n_channels = - dl_symbol("gdk_pixbuf_get_n_channels"); - fp_gdk_pixbuf_get_colorspace = - dl_symbol("gdk_pixbuf_get_colorspace"); - - /* GTK painting */ - fp_gtk_init_check = dl_symbol("gtk_init_check"); - fp_gtk_paint_hline = dl_symbol("gtk_paint_hline"); - fp_gtk_paint_vline = dl_symbol("gtk_paint_vline"); - fp_gtk_paint_shadow = dl_symbol("gtk_paint_shadow"); - fp_gtk_paint_arrow = dl_symbol("gtk_paint_arrow"); - fp_gtk_paint_box = dl_symbol("gtk_paint_box"); - fp_gtk_paint_flat_box = dl_symbol("gtk_paint_flat_box"); - fp_gtk_paint_check = dl_symbol("gtk_paint_check"); - fp_gtk_paint_option = dl_symbol("gtk_paint_option"); - fp_gtk_paint_box_gap = dl_symbol("gtk_paint_box_gap"); - fp_gtk_paint_extension = dl_symbol("gtk_paint_extension"); - fp_gtk_paint_focus = dl_symbol("gtk_paint_focus"); - fp_gtk_paint_slider = dl_symbol("gtk_paint_slider"); - fp_gtk_paint_handle = dl_symbol("gtk_paint_handle"); - fp_gtk_paint_expander = dl_symbol("gtk_paint_expander"); - fp_gtk_style_apply_default_background = - dl_symbol("gtk_style_apply_default_background"); - - /* GTK widgets */ - fp_gtk_arrow_new = dl_symbol("gtk_arrow_new"); - fp_gtk_button_new = dl_symbol("gtk_button_new"); - fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new"); - fp_gtk_check_button_new = dl_symbol("gtk_check_button_new"); - fp_gtk_check_menu_item_new = - dl_symbol("gtk_check_menu_item_new"); - fp_gtk_color_selection_dialog_new = - dl_symbol("gtk_color_selection_dialog_new"); - fp_gtk_entry_new = dl_symbol("gtk_entry_new"); - fp_gtk_fixed_new = dl_symbol("gtk_fixed_new"); - fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new"); - fp_gtk_image_new = dl_symbol("gtk_image_new"); - fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new"); - fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new"); - fp_gtk_hscale_new = dl_symbol("gtk_hscale_new"); - fp_gtk_vscale_new = dl_symbol("gtk_vscale_new"); - fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new"); - fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new"); - fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new"); - fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new"); - fp_gtk_label_new = dl_symbol("gtk_label_new"); - fp_gtk_menu_new = dl_symbol("gtk_menu_new"); - fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new"); - fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new"); - fp_gtk_menu_item_set_submenu = - dl_symbol("gtk_menu_item_set_submenu"); - fp_gtk_notebook_new = dl_symbol("gtk_notebook_new"); - fp_gtk_progress_bar_new = - dl_symbol("gtk_progress_bar_new"); - fp_gtk_progress_bar_set_orientation = - dl_symbol("gtk_progress_bar_set_orientation"); - fp_gtk_radio_button_new = - dl_symbol("gtk_radio_button_new"); - fp_gtk_radio_menu_item_new = - dl_symbol("gtk_radio_menu_item_new"); - fp_gtk_scrolled_window_new = - dl_symbol("gtk_scrolled_window_new"); - fp_gtk_separator_menu_item_new = - dl_symbol("gtk_separator_menu_item_new"); - fp_gtk_text_view_new = dl_symbol("gtk_text_view_new"); - fp_gtk_toggle_button_new = - dl_symbol("gtk_toggle_button_new"); - fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new"); - fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new"); - fp_gtk_viewport_new = dl_symbol("gtk_viewport_new"); - fp_gtk_window_new = dl_symbol("gtk_window_new"); - fp_gtk_window_present = dl_symbol("gtk_window_present"); - fp_gtk_window_move = dl_symbol("gtk_window_move"); - fp_gtk_window_resize = dl_symbol("gtk_window_resize"); - - fp_gtk_dialog_new = dl_symbol("gtk_dialog_new"); - fp_gtk_frame_new = dl_symbol("gtk_frame_new"); - - fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new"); - fp_gtk_container_add = dl_symbol("gtk_container_add"); - fp_gtk_menu_shell_append = - dl_symbol("gtk_menu_shell_append"); - fp_gtk_widget_realize = dl_symbol("gtk_widget_realize"); - fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy"); - fp_gtk_widget_render_icon = - dl_symbol("gtk_widget_render_icon"); - fp_gtk_widget_set_name = - dl_symbol("gtk_widget_set_name"); - fp_gtk_widget_set_parent = - dl_symbol("gtk_widget_set_parent"); - fp_gtk_widget_set_direction = - dl_symbol("gtk_widget_set_direction"); - fp_gtk_widget_style_get = - dl_symbol("gtk_widget_style_get"); - fp_gtk_widget_class_install_style_property = - dl_symbol("gtk_widget_class_install_style_property"); - fp_gtk_widget_class_find_style_property = - dl_symbol("gtk_widget_class_find_style_property"); - fp_gtk_widget_style_get_property = - dl_symbol("gtk_widget_style_get_property"); - fp_pango_font_description_to_string = - dl_symbol("pango_font_description_to_string"); - fp_gtk_settings_get_default = - dl_symbol("gtk_settings_get_default"); - fp_gtk_widget_get_settings = - dl_symbol("gtk_widget_get_settings"); - fp_gtk_border_get_type = dl_symbol("gtk_border_get_type"); - fp_gtk_arrow_set = dl_symbol("gtk_arrow_set"); - fp_gtk_widget_size_request = - dl_symbol("gtk_widget_size_request"); - fp_gtk_range_get_adjustment = - dl_symbol("gtk_range_get_adjustment"); - - fp_gtk_widget_hide = dl_symbol("gtk_widget_hide"); - fp_gtk_main_quit = dl_symbol("gtk_main_quit"); - fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); - fp_gtk_widget_show = dl_symbol("gtk_widget_show"); - fp_gtk_main = dl_symbol("gtk_main"); - - fp_g_path_get_dirname = dl_symbol("g_path_get_dirname"); - - /** - * GLib thread system - */ - if (GLIB_CHECK_VERSION(2, 20, 0)) { - fp_g_thread_get_initialized = dl_symbol_gthread("g_thread_get_initialized"); - } - fp_g_thread_init = dl_symbol_gthread("g_thread_init"); - fp_gdk_threads_init = dl_symbol("gdk_threads_init"); - fp_gdk_threads_enter = dl_symbol("gdk_threads_enter"); - fp_gdk_threads_leave = dl_symbol("gdk_threads_leave"); - - /** - * Functions for sun_awt_X11_GtkFileDialogPeer.c - */ - if (fp_gtk_check_version(2, 4, 0) == NULL) { - // The current GtkFileChooser is available from GTK+ 2.4 - gtk2_file_chooser_load(); - } - - /* Some functions may be missing in pre-2.4 GTK. - We handle them specially here. - */ - fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new"); - if (fp_gtk_combo_box_new == NULL) { - fp_gtk_combo_box_new = dl_symbol("gtk_combo_new"); - } - - fp_gtk_combo_box_entry_new = - dlsym(gtk2_libhandle, "gtk_combo_box_entry_new"); - if (fp_gtk_combo_box_entry_new == NULL) { - fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new"); - new_combo = FALSE; - } - - fp_gtk_separator_tool_item_new = - dlsym(gtk2_libhandle, "gtk_separator_tool_item_new"); - if (fp_gtk_separator_tool_item_new == NULL) { - fp_gtk_separator_tool_item_new = - dl_symbol("gtk_vseparator_new"); - } - - fp_g_list_append = dl_symbol("g_list_append"); - fp_g_list_free = dl_symbol("g_list_free"); - fp_g_list_free_full = dl_symbol("g_list_free_full"); - } - /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION - * Otherwise we can check the return value of setjmp method. - */ - else - { - dlclose(gtk2_libhandle); - gtk2_libhandle = NULL; - - dlclose(gthread_libhandle); - gthread_libhandle = NULL; - - return FALSE; - } - - /* - * Strip the AT-SPI GTK_MODULES if present - */ - gtk_modules_env = getenv ("GTK_MODULES"); - if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) || - (gtk_modules_env && strstr(gtk_modules_env, "gail"))) { - /* careful, strtok modifies its args */ - gchar *tmp_env = strdup(gtk_modules_env); - if (tmp_env) { - /* the new env will be smaller than the old one */ - gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc, - sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env)); - - if (new_env) { - strcpy(new_env, ENV_PREFIX); - - /* strip out 'atk-bridge' and 'gail' */ - size_t PREFIX_LENGTH = strlen(ENV_PREFIX); - gchar *tmp_ptr = NULL; - for (s = strtok_r(tmp_env, ":", &tmp_ptr); s; - s = strtok_r(NULL, ":", &tmp_ptr)) { - if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) { - if (strlen(new_env) > PREFIX_LENGTH) { - new_env = strcat(new_env, ":"); - } - new_env = strcat(new_env, s); - } - } - if (putenv(new_env) != 0) { - /* no free() on success, putenv() doesn't copy string */ - free(new_env); - } - } - free(tmp_env); - } - } - /* - * GTK should be initialized with gtk_init_check() before use. - * - * gtk_init_check installs its own error handlers. It is critical that - * we preserve error handler set from AWT. Otherwise we'll crash on - * BadMatch errors which we would normally ignore. The IO error handler - * is preserved here, too, just for consistency. - */ - AWT_LOCK(); - handler = XSetErrorHandler(NULL); - io_handler = XSetIOErrorHandler(NULL); - - if (fp_gtk_check_version(2, 2, 0) == NULL) { - - // Calling g_thread_init() multiple times leads to crash on GLib < 2.24 - // We can use g_thread_get_initialized () but it is available only for - // GLib >= 2.20. - gboolean is_g_thread_get_initialized = FALSE; - if (GLIB_CHECK_VERSION(2, 20, 0)) { - is_g_thread_get_initialized = fp_g_thread_get_initialized(); - } - - if (!is_g_thread_get_initialized) { - fp_g_thread_init(NULL); - } - - //According the GTK documentation, gdk_threads_init() should be - //called before gtk_init() or gtk_init_check() - fp_gdk_threads_init(); - } - result = (*fp_gtk_init_check)(NULL, NULL); - - XSetErrorHandler(handler); - XSetIOErrorHandler(io_handler); - AWT_UNLOCK(); - - /* Initialize widget array. */ - for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++) - { - gtk2_widgets[i] = NULL; - } - if (result) { - GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); - gtk2_init(gtk); - return gtk; - } - return NULL; -} - -int gtk2_unload() -{ - int i; - char *gtk2_error; - - if (!gtk2_libhandle) - return TRUE; - - /* Release painting objects */ - if (gtk2_white_pixmap != NULL) { - (*fp_g_object_unref)(gtk2_white_pixmap); - (*fp_g_object_unref)(gtk2_black_pixmap); - (*fp_g_object_unref)(gtk2_white_pixbuf); - (*fp_g_object_unref)(gtk2_black_pixbuf); - gtk2_white_pixmap = gtk2_black_pixmap = - gtk2_white_pixbuf = gtk2_black_pixbuf = NULL; - } - gtk2_pixbuf_width = 0; - gtk2_pixbuf_height = 0; - - if (gtk2_window != NULL) { - /* Destroying toplevel widget will destroy all contained widgets */ - (*fp_gtk_widget_destroy)(gtk2_window); - - /* Unset some static data so they get reinitialized on next load */ - gtk2_window = NULL; - } - - dlerror(); - dlclose(gtk2_libhandle); - dlclose(gthread_libhandle); - if ((gtk2_error = dlerror()) != NULL) - { - return FALSE; - } - return TRUE; -} - -/* Dispatch all pending events from the GTK event loop. - * This is needed to catch theme change and update widgets' style. - */ -static void flush_gtk_event_loop() -{ - while( (*fp_g_main_context_iteration)(NULL, FALSE)); -} - -/* - * Initialize components of containment hierarchy. This creates a GtkFixed - * inside a GtkWindow. All widgets get realized. - */ -static void init_containers() -{ - if (gtk2_window == NULL) - { - gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); - gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)(); - (*fp_gtk_container_add)((GtkContainer*)gtk2_window, - (GtkWidget *)gtk2_fixed); - (*fp_gtk_widget_realize)(gtk2_window); - (*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed); - } -} - -/* - * Ensure everything is ready for drawing an element of the specified width - * and height. - * - * We should somehow handle translucent images. GTK can draw to X Drawables - * only, which don't support alpha. When we retrieve the image back from - * the server, translucency information is lost. There're several ways to - * work around this: - * 1) Subclass GdkPixmap and cache translucent objects on client side. This - * requires us to implement parts of X server drawing logic on client side. - * Many X requests can potentially be "translucent"; e.g. XDrawLine with - * fill=tile and a translucent tile is a "translucent" operation, whereas - * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some - * do) intermix transparent and opaque operations which makes caching even - * more problematic. - * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support - * for it (as of version 2.6). Also even in JDS 3 Xorg does not support - * these visuals by default, which makes optimizing for them pointless. - * We can consider doing this at a later point when ARGB visuals become more - * popular. - * 3') GTK has plans to use Cairo as its graphical backend (presumably in - * 2.8), and Cairo supports alpha. With it we could also get rid of the - * unnecessary round trip to server and do all the drawing on client side. - * 4) For now we draw to two different pixmaps and restore alpha channel by - * comparing results. This can be optimized by using subclassed pixmap and - * doing the second drawing only if necessary. -*/ -static void gtk2_init_painting(JNIEnv *env, gint width, gint height) -{ - GdkGC *gc; - GdkPixbuf *white, *black; - - init_containers(); - - if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height) - { - white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height); - black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height); - - if (white == NULL || black == NULL) - { - snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height); - throw_exception(env, "java/lang/RuntimeException", convertionBuffer); - fp_gdk_threads_leave(); - return; - } - - if (gtk2_white_pixmap != NULL) { - /* free old stuff */ - (*fp_g_object_unref)(gtk2_white_pixmap); - (*fp_g_object_unref)(gtk2_black_pixmap); - (*fp_g_object_unref)(gtk2_white_pixbuf); - (*fp_g_object_unref)(gtk2_black_pixbuf); - } - - gtk2_white_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1); - gtk2_black_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1); - - gtk2_white_pixbuf = white; - gtk2_black_pixbuf = black; - - gtk2_pixbuf_width = width; - gtk2_pixbuf_height = height; - } - - /* clear the pixmaps */ - gc = (*fp_gdk_gc_new)(gtk2_white_pixmap); - (*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff); - (*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height); - (*fp_g_object_unref)(gc); - - gc = (*fp_gdk_gc_new)(gtk2_black_pixmap); - (*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000); - (*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height); - (*fp_g_object_unref)(gc); -} - -/* - * Restore image from white and black pixmaps and copy it into destination - * buffer. This method compares two pixbufs taken from white and black - * pixmaps and decodes color and alpha components. Pixbufs are RGB without - * alpha, destination buffer is ABGR. - * - * The return value is the transparency type of the resulting image, either - * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and - * java_awt_Transparency_TRANSLUCENT. - */ -static gint gtk2_copy_image(gint *dst, gint width, gint height) -{ - gint i, j, r, g, b; - guchar *white, *black; - gint stride, padding; - gboolean is_opaque = TRUE; - gboolean is_bitmask = TRUE; - - (*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap, - NULL, 0, 0, 0, 0, width, height); - (*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap, - NULL, 0, 0, 0, 0, width, height); - - white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf); - black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf); - stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf); - padding = stride - width * 4; - if (padding >= 0 && stride > 0) { - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - int r1 = *white++; - int r2 = *black++; - int alpha = 0xff + r2 - r1; - - switch (alpha) { - case 0: /* transparent pixel */ - r = g = b = 0; - black += 3; - white += 3; - is_opaque = FALSE; - break; - - case 0xff: /* opaque pixel */ - r = r2; - g = *black++; - b = *black++; - black++; - white += 3; - break; - - default: /* translucent pixel */ - r = 0xff * r2 / alpha; - g = 0xff * *black++ / alpha; - b = 0xff * *black++ / alpha; - black++; - white += 3; - is_opaque = FALSE; - is_bitmask = FALSE; - break; - } - - *dst++ = (alpha << 24 | r << 16 | g << 8 | b); - } - - white += padding; - black += padding; - } - } - return is_opaque ? java_awt_Transparency_OPAQUE : - (is_bitmask ? java_awt_Transparency_BITMASK : - java_awt_Transparency_TRANSLUCENT); -} - -static void -gtk2_set_direction(GtkWidget *widget, GtkTextDirection dir) -{ - /* - * Some engines (inexplicably) look at the direction of the widget's - * parent, so we need to set the direction of both the widget and its - * parent. - */ - (*fp_gtk_widget_set_direction)(widget, dir); - if (widget->parent != NULL) { - (*fp_gtk_widget_set_direction)(widget->parent, dir); - } -} - -/* - * Initializes the widget to correct state for some engines. - * This is a pure empirical method. - */ -static void init_toggle_widget(WidgetType widget_type, gint synth_state) -{ - gboolean is_active = ((synth_state & SELECTED) != 0); - - if (widget_type == RADIO_BUTTON || - widget_type == CHECK_BOX || - widget_type == TOGGLE_BUTTON) { - ((GtkToggleButton*)gtk2_widget)->active = is_active; - } - - if ((synth_state & FOCUSED) != 0) { - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; - } else { - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; - } - - if ((((synth_state & MOUSE_OVER) != 0) && ((synth_state & PRESSED) == 0)) || - (((synth_state & FOCUSED) != 0) && ((synth_state & PRESSED) != 0))) { - gtk2_widget->state = GTK_STATE_PRELIGHT; - } else if ((synth_state & DISABLED) != 0) { - gtk2_widget->state = GTK_STATE_INSENSITIVE; - } else { - gtk2_widget->state = is_active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL; - } -} - -/* GTK state_type filter */ -static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state) -{ - GtkStateType result = GTK_STATE_NORMAL; - - if ((synth_state & DISABLED) != 0) { - result = GTK_STATE_INSENSITIVE; - } else if ((synth_state & PRESSED) != 0) { - result = GTK_STATE_ACTIVE; - } else if ((synth_state & MOUSE_OVER) != 0) { - result = GTK_STATE_PRELIGHT; - } - return result; -} - -/* GTK shadow_type filter */ -static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, gint synth_state) -{ - GtkShadowType result = GTK_SHADOW_OUT; - - if ((synth_state & SELECTED) != 0) { - result = GTK_SHADOW_IN; - } - return result; -} - - -static GtkWidget* gtk2_get_arrow(GtkArrowType arrow_type, GtkShadowType shadow_type) -{ - GtkWidget *arrow = NULL; - if (NULL == gtk2_widgets[_GTK_ARROW_TYPE]) - { - gtk2_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, shadow_type); - (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, gtk2_widgets[_GTK_ARROW_TYPE]); - (*fp_gtk_widget_realize)(gtk2_widgets[_GTK_ARROW_TYPE]); - } - arrow = gtk2_widgets[_GTK_ARROW_TYPE]; - - (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type); - return arrow; -} - -static GtkAdjustment* create_adjustment() -{ - return (GtkAdjustment *) - (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0); -} - -/** - * Returns a pointer to the cached native widget for the specified widget - * type. - */ -static GtkWidget *gtk2_get_widget(WidgetType widget_type) -{ - gboolean init_result = FALSE; - GtkWidget *result = NULL; - switch (widget_type) - { - case BUTTON: - case TABLE_HEADER: - if (init_result = (NULL == gtk2_widgets[_GTK_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)(); - } - result = gtk2_widgets[_GTK_BUTTON_TYPE]; - break; - case CHECK_BOX: - if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_CHECK_BUTTON_TYPE] = - (*fp_gtk_check_button_new)(); - } - result = gtk2_widgets[_GTK_CHECK_BUTTON_TYPE]; - break; - case CHECK_BOX_MENU_ITEM: - if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE] = - (*fp_gtk_check_menu_item_new)(); - } - result = gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE]; - break; - /************************************************************ - * Creation a dedicated color chooser is dangerous because - * it deadlocks the EDT - ************************************************************/ -/* case COLOR_CHOOSER: - if (init_result = - (NULL == gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE])) - { - gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] = - (*fp_gtk_color_selection_dialog_new)(NULL); - } - result = gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]; - break;*/ - case COMBO_BOX: - if (init_result = (NULL == gtk2_widgets[_GTK_COMBO_BOX_TYPE])) - { - gtk2_widgets[_GTK_COMBO_BOX_TYPE] = - (*fp_gtk_combo_box_new)(); - } - result = gtk2_widgets[_GTK_COMBO_BOX_TYPE]; - break; - case COMBO_BOX_ARROW_BUTTON: - if (init_result = - (NULL == gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] = - (*fp_gtk_toggle_button_new)(); - } - result = gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]; - break; - case COMBO_BOX_TEXT_FIELD: - if (init_result = - (NULL == gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE])) - { - result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] = - (*fp_gtk_entry_new)(); - } - result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]; - break; - case DESKTOP_ICON: - case INTERNAL_FRAME_TITLE_PANE: - case LABEL: - if (init_result = (NULL == gtk2_widgets[_GTK_LABEL_TYPE])) - { - gtk2_widgets[_GTK_LABEL_TYPE] = - (*fp_gtk_label_new)(NULL); - } - result = gtk2_widgets[_GTK_LABEL_TYPE]; - break; - case DESKTOP_PANE: - case PANEL: - case ROOT_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_CONTAINER_TYPE])) - { - /* There is no constructor for a container type. I've - * chosen GtkFixed container since it has a default - * constructor. - */ - gtk2_widgets[_GTK_CONTAINER_TYPE] = - (*fp_gtk_fixed_new)(); - } - result = gtk2_widgets[_GTK_CONTAINER_TYPE]; - break; - case EDITOR_PANE: - case TEXT_AREA: - case TEXT_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_TEXT_VIEW_TYPE])) - { - gtk2_widgets[_GTK_TEXT_VIEW_TYPE] = - (*fp_gtk_text_view_new)(); - } - result = gtk2_widgets[_GTK_TEXT_VIEW_TYPE]; - break; - case FORMATTED_TEXT_FIELD: - case PASSWORD_FIELD: - case TEXT_FIELD: - if (init_result = (NULL == gtk2_widgets[_GTK_ENTRY_TYPE])) - { - gtk2_widgets[_GTK_ENTRY_TYPE] = - (*fp_gtk_entry_new)(); - } - result = gtk2_widgets[_GTK_ENTRY_TYPE]; - break; - case HANDLE_BOX: - if (init_result = (NULL == gtk2_widgets[_GTK_HANDLE_BOX_TYPE])) - { - gtk2_widgets[_GTK_HANDLE_BOX_TYPE] = - (*fp_gtk_handle_box_new)(); - } - result = gtk2_widgets[_GTK_HANDLE_BOX_TYPE]; - break; - case HSCROLL_BAR: - case HSCROLL_BAR_BUTTON_LEFT: - case HSCROLL_BAR_BUTTON_RIGHT: - case HSCROLL_BAR_TRACK: - case HSCROLL_BAR_THUMB: - if (init_result = (NULL == gtk2_widgets[_GTK_HSCROLLBAR_TYPE])) - { - gtk2_widgets[_GTK_HSCROLLBAR_TYPE] = - (*fp_gtk_hscrollbar_new)(create_adjustment()); - } - result = gtk2_widgets[_GTK_HSCROLLBAR_TYPE]; - break; - case HSEPARATOR: - if (init_result = (NULL == gtk2_widgets[_GTK_HSEPARATOR_TYPE])) - { - gtk2_widgets[_GTK_HSEPARATOR_TYPE] = - (*fp_gtk_hseparator_new)(); - } - result = gtk2_widgets[_GTK_HSEPARATOR_TYPE]; - break; - case HSLIDER: - case HSLIDER_THUMB: - case HSLIDER_TRACK: - if (init_result = (NULL == gtk2_widgets[_GTK_HSCALE_TYPE])) - { - gtk2_widgets[_GTK_HSCALE_TYPE] = - (*fp_gtk_hscale_new)(NULL); - } - result = gtk2_widgets[_GTK_HSCALE_TYPE]; - break; - case HSPLIT_PANE_DIVIDER: - case SPLIT_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_HPANED_TYPE])) - { - gtk2_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)(); - } - result = gtk2_widgets[_GTK_HPANED_TYPE]; - break; - case IMAGE: - if (init_result = (NULL == gtk2_widgets[_GTK_IMAGE_TYPE])) - { - gtk2_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)(); - } - result = gtk2_widgets[_GTK_IMAGE_TYPE]; - break; - case INTERNAL_FRAME: - if (init_result = (NULL == gtk2_widgets[_GTK_WINDOW_TYPE])) - { - gtk2_widgets[_GTK_WINDOW_TYPE] = - (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); - } - result = gtk2_widgets[_GTK_WINDOW_TYPE]; - break; - case TOOL_TIP: - if (init_result = (NULL == gtk2_widgets[_GTK_TOOLTIP_TYPE])) - { - result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); - (*fp_gtk_widget_set_name)(result, "gtk-tooltips"); - gtk2_widgets[_GTK_TOOLTIP_TYPE] = result; - } - result = gtk2_widgets[_GTK_TOOLTIP_TYPE]; - break; - case LIST: - case TABLE: - case TREE: - case TREE_CELL: - if (init_result = (NULL == gtk2_widgets[_GTK_TREE_VIEW_TYPE])) - { - gtk2_widgets[_GTK_TREE_VIEW_TYPE] = - (*fp_gtk_tree_view_new)(); - } - result = gtk2_widgets[_GTK_TREE_VIEW_TYPE]; - break; - case TITLED_BORDER: - if (init_result = (NULL == gtk2_widgets[_GTK_FRAME_TYPE])) - { - gtk2_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL); - } - result = gtk2_widgets[_GTK_FRAME_TYPE]; - break; - case POPUP_MENU: - if (init_result = (NULL == gtk2_widgets[_GTK_MENU_TYPE])) - { - gtk2_widgets[_GTK_MENU_TYPE] = - (*fp_gtk_menu_new)(); - } - result = gtk2_widgets[_GTK_MENU_TYPE]; - break; - case MENU: - case MENU_ITEM: - case MENU_ITEM_ACCELERATOR: - if (init_result = (NULL == gtk2_widgets[_GTK_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_MENU_ITEM_TYPE] = - (*fp_gtk_menu_item_new)(); - } - result = gtk2_widgets[_GTK_MENU_ITEM_TYPE]; - break; - case MENU_BAR: - if (init_result = (NULL == gtk2_widgets[_GTK_MENU_BAR_TYPE])) - { - gtk2_widgets[_GTK_MENU_BAR_TYPE] = - (*fp_gtk_menu_bar_new)(); - } - result = gtk2_widgets[_GTK_MENU_BAR_TYPE]; - break; - case COLOR_CHOOSER: - case OPTION_PANE: - if (init_result = (NULL == gtk2_widgets[_GTK_DIALOG_TYPE])) - { - gtk2_widgets[_GTK_DIALOG_TYPE] = - (*fp_gtk_dialog_new)(); - } - result = gtk2_widgets[_GTK_DIALOG_TYPE]; - break; - case POPUP_MENU_SEPARATOR: - if (init_result = - (NULL == gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] = - (*fp_gtk_separator_menu_item_new)(); - } - result = gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]; - break; - case HPROGRESS_BAR: - if (init_result = (NULL == gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE])) - { - gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE] = - (*fp_gtk_progress_bar_new)(); - } - result = gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE]; - break; - case VPROGRESS_BAR: - if (init_result = (NULL == gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE])) - { - gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE] = - (*fp_gtk_progress_bar_new)(); - /* - * Vertical JProgressBars always go bottom-to-top, - * regardless of the ComponentOrientation. - */ - (*fp_gtk_progress_bar_set_orientation)( - (GtkProgressBar *)gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE], - GTK_PROGRESS_BOTTOM_TO_TOP); - } - result = gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE]; - break; - case RADIO_BUTTON: - if (init_result = (NULL == gtk2_widgets[_GTK_RADIO_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_RADIO_BUTTON_TYPE] = - (*fp_gtk_radio_button_new)(NULL); - } - result = gtk2_widgets[_GTK_RADIO_BUTTON_TYPE]; - break; - case RADIO_BUTTON_MENU_ITEM: - if (init_result = - (NULL == gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE])) - { - gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE] = - (*fp_gtk_radio_menu_item_new)(NULL); - } - result = gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE]; - break; - case SCROLL_PANE: - if (init_result = - (NULL == gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE])) - { - gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE] = - (*fp_gtk_scrolled_window_new)(NULL, NULL); - } - result = gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE]; - break; - case SPINNER: - case SPINNER_ARROW_BUTTON: - case SPINNER_TEXT_FIELD: - if (init_result = (NULL == gtk2_widgets[_GTK_SPIN_BUTTON_TYPE])) - { - result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE] = - (*fp_gtk_spin_button_new)(NULL, 0, 0); - } - result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE]; - break; - case TABBED_PANE: - case TABBED_PANE_TAB_AREA: - case TABBED_PANE_CONTENT: - case TABBED_PANE_TAB: - if (init_result = (NULL == gtk2_widgets[_GTK_NOTEBOOK_TYPE])) - { - gtk2_widgets[_GTK_NOTEBOOK_TYPE] = - (*fp_gtk_notebook_new)(); - } - result = gtk2_widgets[_GTK_NOTEBOOK_TYPE]; - break; - case TOGGLE_BUTTON: - if (init_result = (NULL == gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE])) - { - gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE] = - (*fp_gtk_toggle_button_new)(); - } - result = gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE]; - break; - case TOOL_BAR: - case TOOL_BAR_DRAG_WINDOW: - if (init_result = (NULL == gtk2_widgets[_GTK_TOOLBAR_TYPE])) - { - gtk2_widgets[_GTK_TOOLBAR_TYPE] = - (*fp_gtk_toolbar_new)(); - } - result = gtk2_widgets[_GTK_TOOLBAR_TYPE]; - break; - case TOOL_BAR_SEPARATOR: - if (init_result = - (NULL == gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE])) - { - gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] = - (*fp_gtk_separator_tool_item_new)(); - } - result = gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]; - break; - case VIEWPORT: - if (init_result = (NULL == gtk2_widgets[_GTK_VIEWPORT_TYPE])) - { - GtkAdjustment *adjustment = create_adjustment(); - gtk2_widgets[_GTK_VIEWPORT_TYPE] = - (*fp_gtk_viewport_new)(adjustment, adjustment); - } - result = gtk2_widgets[_GTK_VIEWPORT_TYPE]; - break; - case VSCROLL_BAR: - case VSCROLL_BAR_BUTTON_UP: - case VSCROLL_BAR_BUTTON_DOWN: - case VSCROLL_BAR_TRACK: - case VSCROLL_BAR_THUMB: - if (init_result = (NULL == gtk2_widgets[_GTK_VSCROLLBAR_TYPE])) - { - gtk2_widgets[_GTK_VSCROLLBAR_TYPE] = - (*fp_gtk_vscrollbar_new)(create_adjustment()); - } - result = gtk2_widgets[_GTK_VSCROLLBAR_TYPE]; - break; - case VSEPARATOR: - if (init_result = (NULL == gtk2_widgets[_GTK_VSEPARATOR_TYPE])) - { - gtk2_widgets[_GTK_VSEPARATOR_TYPE] = - (*fp_gtk_vseparator_new)(); - } - result = gtk2_widgets[_GTK_VSEPARATOR_TYPE]; - break; - case VSLIDER: - case VSLIDER_THUMB: - case VSLIDER_TRACK: - if (init_result = (NULL == gtk2_widgets[_GTK_VSCALE_TYPE])) - { - gtk2_widgets[_GTK_VSCALE_TYPE] = - (*fp_gtk_vscale_new)(NULL); - } - result = gtk2_widgets[_GTK_VSCALE_TYPE]; - /* - * Vertical JSliders start at the bottom, while vertical - * GtkVScale widgets start at the top (by default), so to fix - * this we set the "inverted" flag to get the Swing behavior. - */ - ((GtkRange*)result)->inverted = 1; - break; - case VSPLIT_PANE_DIVIDER: - if (init_result = (NULL == gtk2_widgets[_GTK_VPANED_TYPE])) - { - gtk2_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)(); - } - result = gtk2_widgets[_GTK_VPANED_TYPE]; - break; - default: - result = NULL; - break; - } - - if (result != NULL && init_result) - { - if (widget_type == RADIO_BUTTON_MENU_ITEM || - widget_type == CHECK_BOX_MENU_ITEM || - widget_type == MENU_ITEM || - widget_type == MENU || - widget_type == POPUP_MENU_SEPARATOR) - { - GtkWidget *menu = gtk2_get_widget(POPUP_MENU); - (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result); - } - else if (widget_type == POPUP_MENU) - { - GtkWidget *menu_bar = gtk2_get_widget(MENU_BAR); - GtkWidget *root_menu = (*fp_gtk_menu_item_new)(); - (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result); - (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu); - } - else if (widget_type == COMBO_BOX_ARROW_BUTTON || - widget_type == COMBO_BOX_TEXT_FIELD) - { - /* - * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry - * in order to trick engines into thinking it's a real combobox - * arrow button/text field. - */ - GtkWidget *combo = (*fp_gtk_combo_box_entry_new)(); - - if (new_combo && widget_type == COMBO_BOX_ARROW_BUTTON) { - (*fp_gtk_widget_set_parent)(result, combo); - ((GtkBin*)combo)->child = result; - } else { - (*fp_gtk_container_add)((GtkContainer *)combo, result); - } - (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, combo); - } - else if (widget_type != TOOL_TIP && - widget_type != INTERNAL_FRAME && - widget_type != OPTION_PANE) - { - (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, result); - } - (*fp_gtk_widget_realize)(result); - } - return result; -} - -void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkArrowType arrow_type, gboolean fill) -{ - static int w, h; - static GtkRequisition size; - - if (widget_type == COMBO_BOX_ARROW_BUTTON || widget_type == TABLE) - gtk2_widget = gtk2_get_arrow(arrow_type, shadow_type); - else - gtk2_widget = gtk2_get_widget(widget_type); - - switch (widget_type) - { - case SPINNER_ARROW_BUTTON: - x = 1; - y = ((arrow_type == GTK_ARROW_UP) ? 2 : 0); - height -= 2; - width -= 3; - - w = width / 2; - w -= w % 2 - 1; - h = (w + 1) / 2; - break; - - case HSCROLL_BAR_BUTTON_LEFT: - case HSCROLL_BAR_BUTTON_RIGHT: - case VSCROLL_BAR_BUTTON_UP: - case VSCROLL_BAR_BUTTON_DOWN: - w = width / 2; - h = height / 2; - break; - - case COMBO_BOX_ARROW_BUTTON: - case TABLE: - x = 1; - (*fp_gtk_widget_size_request)(gtk2_widget, &size); - w = size.width - ((GtkMisc*)gtk2_widget)->xpad * 2; - h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2; - w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7; - break; - - default: - w = width; - h = height; - break; - } - x += (width - w) / 2; - y += (height - h) / 2; - - (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, arrow_type, fill, - x, y, w, h); - (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, arrow_type, fill, - x, y, w, h); -} - -static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir) -{ - gtk2_widget = gtk2_get_widget(widget_type); - - /* - * The clearlooks engine sometimes looks at the widget's state field - * instead of just the state_type variable that we pass in, so to account - * for those cases we set the widget's state field accordingly. The - * flags field is similarly important for things like focus/default state. - */ - gtk2_widget->state = state_type; - - if (widget_type == HSLIDER_TRACK) { - /* - * For horizontal JSliders with right-to-left orientation, we need - * to set the "inverted" flag to match the native GTK behavior where - * the foreground highlight is on the right side of the slider thumb. - * This is needed especially for the ubuntulooks engine, which looks - * exclusively at the "inverted" flag to determine on which side of - * the thumb to paint the highlight... - */ - ((GtkRange*)gtk2_widget)->inverted = (dir == GTK_TEXT_DIR_RTL); - - /* - * Note however that other engines like clearlooks will look at both - * the "inverted" field and the text direction to determine how - * the foreground highlight is painted: - * !inverted && ltr --> paint highlight on left side - * !inverted && rtl --> paint highlight on right side - * inverted && ltr --> paint highlight on right side - * inverted && rtl --> paint highlight on left side - * So the only way to reliably get the desired results for horizontal - * JSlider (i.e., highlight on left side for LTR ComponentOrientation - * and highlight on right side for RTL ComponentOrientation) is to - * always override text direction as LTR, and then set the "inverted" - * flag accordingly (as we have done above). - */ - dir = GTK_TEXT_DIR_LTR; - } - - /* - * Some engines (e.g. clearlooks) will paint the shadow of certain - * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the - * the text direction. - */ - gtk2_set_direction(gtk2_widget, dir); - - switch (widget_type) { - case BUTTON: - if (synth_state & DEFAULT) { - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_DEFAULT; - } else { - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_DEFAULT; - } - break; - case TOGGLE_BUTTON: - init_toggle_widget(widget_type, synth_state); - break; - case HSCROLL_BAR_BUTTON_LEFT: - /* - * The clearlooks engine will draw a "left" button when: - * x == w->allocation.x - * - * The ubuntulooks engine will draw a "left" button when: - * [x,y,width,height] - * intersects - * [w->alloc.x,w->alloc.y,width,height] - * - * The values that are set below should ensure that a "left" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x; - gtk2_widget->allocation.y = y; - gtk2_widget->allocation.width = width; - gtk2_widget->allocation.height = height; - break; - case HSCROLL_BAR_BUTTON_RIGHT: - /* - * The clearlooks engine will draw a "right" button when: - * x + width == w->allocation.x + w->allocation.width - * - * The ubuntulooks engine will draw a "right" button when: - * [x,y,width,height] - * does not intersect - * [w->alloc.x,w->alloc.y,width,height] - * but does intersect - * [w->alloc.x+width,w->alloc.y,width,height] - * - * The values that are set below should ensure that a "right" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x+width; - gtk2_widget->allocation.y = 0; - gtk2_widget->allocation.width = 0; - gtk2_widget->allocation.height = height; - break; - case VSCROLL_BAR_BUTTON_UP: - /* - * The clearlooks engine will draw an "up" button when: - * y == w->allocation.y - * - * The ubuntulooks engine will draw an "up" button when: - * [x,y,width,height] - * intersects - * [w->alloc.x,w->alloc.y,width,height] - * - * The values that are set below should ensure that an "up" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x; - gtk2_widget->allocation.y = y; - gtk2_widget->allocation.width = width; - gtk2_widget->allocation.height = height; - break; - case VSCROLL_BAR_BUTTON_DOWN: - /* - * The clearlooks engine will draw a "down" button when: - * y + height == w->allocation.y + w->allocation.height - * - * The ubuntulooks engine will draw a "down" button when: - * [x,y,width,height] - * does not intersect - * [w->alloc.x,w->alloc.y,width,height] - * but does intersect - * [w->alloc.x,w->alloc.y+height,width,height] - * - * The values that are set below should ensure that a "down" - * button is rendered for both of these (and other) engines. - */ - gtk2_widget->allocation.x = x; - gtk2_widget->allocation.y = y+height; - gtk2_widget->allocation.width = width; - gtk2_widget->allocation.height = 0; - break; - default: - break; - } - - (*fp_gtk_paint_box)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - (*fp_gtk_paint_box)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - - /* - * Reset the text direction to the default value so that we don't - * accidentally affect other operations and widgets. - */ - gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); -} - -void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - GtkPositionType gap_side, gint gap_x, gint gap_width) -{ - /* Clearlooks needs a real clip area to paint the gap properly */ - GdkRectangle area = { x, y, width, height }; - - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, &area, gtk2_widget, detail, - x, y, width, height, gap_side, gap_x, gap_width); - (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, &area, gtk2_widget, detail, - x, y, width, height, gap_side, gap_x, gap_width); -} - -static void gtk2_paint_check(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); - GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); - - gtk2_widget = gtk2_get_widget(widget_type); - init_toggle_widget(widget_type, synth_state); - - (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); - (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); -} - -static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height, - GtkExpanderStyle expander_style) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap, - state_type, NULL, gtk2_widget, detail, - x + width / 2, y + height / 2, expander_style); - (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap, - state_type, NULL, gtk2_widget, detail, - x + width / 2, y + height / 2, expander_style); -} - -static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkPositionType gap_side) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, gap_side); - (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, gap_side); -} - -static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, gboolean has_focus) -{ - gtk2_widget = gtk2_get_widget(widget_type); - - if (has_focus) - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; - else - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; - - (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); - (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap, - state_type, shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); -} - -static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, - const char *detail, gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type, - NULL, gtk2_widget, detail, x, y, width, height); - (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type, - NULL, gtk2_widget, detail, x, y, width, height); -} - -static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); - (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); -} - -static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type, - NULL, gtk2_widget, detail, x, x + width, y); - (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type, - NULL, gtk2_widget, detail, x, x + width, y); -} - -static void gtk2_paint_option(WidgetType widget_type, gint synth_state, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); - GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); - - gtk2_widget = gtk2_get_widget(widget_type); - init_toggle_widget(widget_type, synth_state); - - (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); - (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height); -} - -static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, - gint synth_state, GtkTextDirection dir) -{ - gtk2_widget = gtk2_get_widget(widget_type); - - /* - * The clearlooks engine sometimes looks at the widget's state field - * instead of just the state_type variable that we pass in, so to account - * for those cases we set the widget's state field accordingly. The - * flags field is similarly important for things like focus state. - */ - gtk2_widget->state = state_type; - - /* - * Some engines (e.g. clearlooks) will paint the shadow of certain - * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the - * the text direction. - */ - gtk2_set_direction(gtk2_widget, dir); - - switch (widget_type) { - case COMBO_BOX_TEXT_FIELD: - case FORMATTED_TEXT_FIELD: - case PASSWORD_FIELD: - case SPINNER_TEXT_FIELD: - case TEXT_FIELD: - if (synth_state & FOCUSED) { - ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; - } else { - ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; - } - break; - default: - break; - } - - (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, x, y, width, height); - - /* - * Reset the text direction to the default value so that we don't - * accidentally affect other operations and widgets. - */ - gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); -} - -static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, - GtkShadowType shadow_type, const gchar *detail, - gint x, gint y, gint width, gint height, GtkOrientation orientation, - gboolean has_focus) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); - (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type, - shadow_type, NULL, gtk2_widget, detail, - x, y, width, height, orientation); -} - -static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, - const gchar *detail, gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type, - NULL, gtk2_widget, detail, y, y + height, x); - (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type, - NULL, gtk2_widget, detail, y, y + height, x); -} - -static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, - gint x, gint y, gint width, gint height) -{ - gtk2_widget = gtk2_get_widget(widget_type); - (*fp_gtk_style_apply_default_background)(gtk2_widget->style, - gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height); - (*fp_gtk_style_apply_default_background)(gtk2_widget->style, - gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height); -} - -static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, - GtkIconSize size, GtkTextDirection direction, const char *detail) -{ - init_containers(); - gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type); - gtk2_widget->state = GTK_STATE_NORMAL; - (*fp_gtk_widget_set_direction)(gtk2_widget, direction); - return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail); -} - -static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, - jmethodID icon_upcall_method, jobject this) { - if (!pixbuf) { - return JNI_FALSE; - } - guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); - if (pixbuf_data) { - int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - int width = (*fp_gdk_pixbuf_get_width)(pixbuf); - int height = (*fp_gdk_pixbuf_get_height)(pixbuf); - int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); - int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); - gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); - - jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - - (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), - (jbyte *)pixbuf_data); - (*fp_g_object_unref)(pixbuf); - - /* Call the callback method to create the image on the Java side. */ - (*env)->CallVoidMethod(env, this, icon_upcall_method, data, - width, height, row_stride, bps, channels, alpha); - return JNI_TRUE; - } - return JNI_FALSE; -} - -static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename, - GError **error, jmethodID icon_upcall_method, jobject this) { - GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); - return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); -} - -static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type, - const gchar *stock_id, GtkIconSize size, - GtkTextDirection direction, const char *detail, - jmethodID icon_upcall_method, jobject this) { - GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size, - direction, detail); - return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); -} - -/*************************************************/ -static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - GtkStyle* style = gtk2_widget->style; - return style->xthickness; -} - -static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - GtkStyle* style = gtk2_widget->style; - return style->ythickness; -} - -/*************************************************/ -static guint8 recode_color(guint16 channel) -{ - return (guint8)(channel>>8); -} - -static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, - GtkStateType state_type, ColorType color_type) -{ - gint result = 0; - GdkColor *color = NULL; - - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - GtkStyle* style = gtk2_widget->style; - - switch (color_type) - { - case FOREGROUND: - color = &(style->fg[state_type]); - break; - case BACKGROUND: - color = &(style->bg[state_type]); - break; - case TEXT_FOREGROUND: - color = &(style->text[state_type]); - break; - case TEXT_BACKGROUND: - color = &(style->base[state_type]); - break; - case LIGHT: - color = &(style->light[state_type]); - break; - case DARK: - color = &(style->dark[state_type]); - break; - case MID: - color = &(style->mid[state_type]); - break; - case FOCUS: - case BLACK: - color = &(style->black); - break; - case WHITE: - color = &(style->white); - break; - } - - if (color) - result = recode_color(color->red) << 16 | - recode_color(color->green) << 8 | - recode_color(color->blue); - - return result; -} - -/*************************************************/ -static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); -static jobject create_Integer(JNIEnv *env, jint int_value); -static jobject create_Long(JNIEnv *env, jlong long_value); -static jobject create_Float(JNIEnv *env, jfloat float_value); -static jobject create_Double(JNIEnv *env, jdouble double_value); -static jobject create_Character(JNIEnv *env, jchar char_value); -static jobject create_Insets(JNIEnv *env, GtkBorder *border); - -static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, - const char* key) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - - GValue value; - value.g_type = 0; - - GParamSpec* param = (*fp_gtk_widget_class_find_style_property)( - ((GTypeInstance*)gtk2_widget)->g_class, key); - if( param ) - { - (*fp_g_value_init)( &value, param->value_type ); - (*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value); - - if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN )) - { - gboolean val = (*fp_g_value_get_boolean)(&value); - return create_Boolean(env, (jboolean)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR )) - { - gchar val = (*fp_g_value_get_char)(&value); - return create_Character(env, (jchar)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR )) - { - guchar val = (*fp_g_value_get_uchar)(&value); - return create_Character(env, (jchar)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT )) - { - gint val = (*fp_g_value_get_int)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT )) - { - guint val = (*fp_g_value_get_uint)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_LONG )) - { - glong val = (*fp_g_value_get_long)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG )) - { - gulong val = (*fp_g_value_get_ulong)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 )) - { - gint64 val = (*fp_g_value_get_int64)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 )) - { - guint64 val = (*fp_g_value_get_uint64)(&value); - return create_Long(env, (jlong)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT )) - { - gfloat val = (*fp_g_value_get_float)(&value); - return create_Float(env, (jfloat)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE )) - { - gdouble val = (*fp_g_value_get_double)(&value); - return create_Double(env, (jdouble)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM )) - { - gint val = (*fp_g_value_get_enum)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS )) - { - guint val = (*fp_g_value_get_flags)(&value); - return create_Integer(env, (jint)val); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_STRING )) - { - const gchar* val = (*fp_g_value_get_string)(&value); - - /* We suppose that all values come in C locale and - * utf-8 representation of a string is the same as - * the string itself. If this isn't so we should - * use g_convert. - */ - return (*env)->NewStringUTF(env, val); - } - else if( (*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER )) - { - GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value); - return border ? create_Insets(env, border) : NULL; - } - - /* TODO: Other types are not supported yet.*/ -/* else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM )) - { - GParamSpec* val = (*fp_g_value_get_param)(&value); - printf( "Param: %p\n", val ); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED )) - { - gpointer* val = (*fp_g_value_get_boxed)(&value); - printf( "Boxed: %p\n", val ); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER )) - { - gpointer* val = (*fp_g_value_get_pointer)(&value); - printf( "Pointer: %p\n", val ); - } - else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT )) - { - GObject* val = (GObject*)(*fp_g_value_get_object)(&value); - printf( "Object: %p\n", val ); - }*/ - } - - return NULL; -} - -static void gtk2_set_range_value(WidgetType widget_type, jdouble value, - jdouble min, jdouble max, jdouble visible) -{ - GtkAdjustment *adj; - - gtk2_widget = gtk2_get_widget(widget_type); - - adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget); - adj->value = (gdouble)value; - adj->lower = (gdouble)min; - adj->upper = (gdouble)max; - adj->page_size = (gdouble)visible; -} - -/*************************************************/ -static jobject create_Object(JNIEnv *env, jmethodID *cid, - const char* class_name, - const char* signature, - jvalue* value) -{ - jclass class; - jobject result; - - class = (*env)->FindClass(env, class_name); - if( class == NULL ) - return NULL; /* can't find/load the class, exception thrown */ - - if( *cid == NULL) - { - *cid = (*env)->GetMethodID(env, class, "", signature); - if( *cid == NULL ) - { - (*env)->DeleteLocalRef(env, class); - return NULL; /* can't find/get the method, exception thrown */ - } - } - - result = (*env)->NewObjectA(env, class, *cid, value); - - (*env)->DeleteLocalRef(env, class); - return result; -} - -jobject create_Boolean(JNIEnv *env, jboolean boolean_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.z = boolean_value; - - return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value); -} - -jobject create_Integer(JNIEnv *env, jint int_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.i = int_value; - - return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value); -} - -jobject create_Long(JNIEnv *env, jlong long_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.j = long_value; - - return create_Object(env, &cid, "java/lang/Long", "(J)V", &value); -} - -jobject create_Float(JNIEnv *env, jfloat float_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.f = float_value; - - return create_Object(env, &cid, "java/lang/Float", "(F)V", &value); -} - -jobject create_Double(JNIEnv *env, jdouble double_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.d = double_value; - - return create_Object(env, &cid, "java/lang/Double", "(D)V", &value); -} - -jobject create_Character(JNIEnv *env, jchar char_value) -{ - static jmethodID cid = NULL; - jvalue value; - - value.c = char_value; - - return create_Object(env, &cid, "java/lang/Character", "(C)V", &value); -} - - -jobject create_Insets(JNIEnv *env, GtkBorder *border) -{ - static jmethodID cid = NULL; - jvalue values[4]; - - values[0].i = border->top; - values[1].i = border->left; - values[2].i = border->bottom; - values[3].i = border->right; - - return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values); -} - -/*********************************************/ -static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) -{ - init_containers(); - - gtk2_widget = gtk2_get_widget(widget_type); - jstring result = NULL; - GtkStyle* style = gtk2_widget->style; - - if (style && style->font_desc) - { - gchar* val = (*fp_pango_font_description_to_string)(style->font_desc); - result = (*env)->NewStringUTF(env, val); - (*fp_g_free)( val ); - } - - return result; -} - -/***********************************************/ -static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key) -{ - jobject result = NULL; - gchar* strval = NULL; - - (*fp_g_object_get)(settings, key, &strval, NULL); - result = (*env)->NewStringUTF(env, strval); - (*fp_g_free)(strval); - - return result; -} - -static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) -{ - gint intval = 0; - (*fp_g_object_get)(settings, key, &intval, NULL); - return create_Integer(env, intval); -} - -static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) -{ - gint intval = 0; - (*fp_g_object_get)(settings, key, &intval, NULL); - return create_Boolean(env, intval); -} - -static jobject gtk2_get_setting(JNIEnv *env, Setting property) -{ - GtkSettings* settings = (*fp_gtk_settings_get_default)(); - - switch (property) - { - case GTK_FONT_NAME: - return get_string_property(env, settings, "gtk-font-name"); - case GTK_ICON_SIZES: - return get_string_property(env, settings, "gtk-icon-sizes"); - case GTK_CURSOR_BLINK: - return get_boolean_property(env, settings, "gtk-cursor-blink"); - case GTK_CURSOR_BLINK_TIME: - return get_integer_property(env, settings, "gtk-cursor-blink-time"); - } - - return NULL; -} - -static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x, - jint y, jint width, jint height, jint jwidth, int dx, int dy) { - GdkPixbuf *pixbuf; - jint *ary; - - GdkWindow *root = (*fp_gdk_get_default_root_window)(); - - pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y, - 0, 0, width, height); - - if (pixbuf) { - int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); - int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); - - if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width - && (*fp_gdk_pixbuf_get_height)(pixbuf) == height - && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 - && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB - && nchan >= 3 - ) { - guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); - - ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); - if (ary) { - jint _x, _y; - int index; - for (_y = 0; _y < height; _y++) { - for (_x = 0; _x < width; _x++) { - p = pix + (intptr_t) _y * stride + _x * nchan; - - index = (_y + dy) * jwidth + (_x + dx); - ary[index] = 0xff000000 - | (p[0] << 16) - | (p[1] << 8) - | (p[2]); - - } - } - (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); - } - } - (*fp_g_object_unref)(pixbuf); - } - return JNI_FALSE; -} - -static GdkWindow* gtk2_get_window(void *widget) { - return ((GtkWidget*)widget)->window; -} - -void gtk2_init(GtkApi* gtk) { - gtk->version = GTK_2; - - gtk->show_uri_load = >k2_show_uri_load; - gtk->unload = >k2_unload; - gtk->flush_event_loop = &flush_gtk_event_loop; - gtk->gtk_check_version = fp_gtk_check_version; - gtk->get_setting = >k2_get_setting; - - gtk->paint_arrow = >k2_paint_arrow; - gtk->paint_box = >k2_paint_box; - gtk->paint_box_gap = >k2_paint_box_gap; - gtk->paint_expander = >k2_paint_expander; - gtk->paint_extension = >k2_paint_extension; - gtk->paint_flat_box = >k2_paint_flat_box; - gtk->paint_focus = >k2_paint_focus; - gtk->paint_handle = >k2_paint_handle; - gtk->paint_hline = >k2_paint_hline; - gtk->paint_vline = >k2_paint_vline; - gtk->paint_option = >k2_paint_option; - gtk->paint_shadow = >k2_paint_shadow; - gtk->paint_slider = >k2_paint_slider; - gtk->paint_background = >k_paint_background; - gtk->paint_check = >k2_paint_check; - gtk->set_range_value = >k2_set_range_value; - - gtk->init_painting = >k2_init_painting; - gtk->copy_image = >k2_copy_image; - - gtk->get_xthickness = >k2_get_xthickness; - gtk->get_ythickness = >k2_get_ythickness; - gtk->get_color_for_state = >k2_get_color_for_state; - gtk->get_class_value = >k2_get_class_value; - - gtk->get_pango_font_name = >k2_get_pango_font_name; - gtk->get_icon_data = >k2_get_icon_data; - gtk->get_file_icon_data = >k2_get_file_icon_data; - gtk->gdk_threads_enter = fp_gdk_threads_enter; - gtk->gdk_threads_leave = fp_gdk_threads_leave; - gtk->gtk_show_uri = fp_gtk_show_uri; - gtk->get_drawable_data = >k2_get_drawable_data; - gtk->g_free = fp_g_free; - - gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; - gtk->gtk_widget_hide = fp_gtk_widget_hide; - gtk->gtk_main_quit = fp_gtk_main_quit; - gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; - gtk->gtk_file_chooser_set_current_folder = - fp_gtk_file_chooser_set_current_folder; - gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; - gtk->gtk_file_chooser_set_current_name = - fp_gtk_file_chooser_set_current_name; - gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; - gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; - gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; - gtk->gtk_file_filter_new = fp_gtk_file_filter_new; - gtk->gtk_file_chooser_set_do_overwrite_confirmation = - fp_gtk_file_chooser_set_do_overwrite_confirmation; - gtk->gtk_file_chooser_set_select_multiple = - fp_gtk_file_chooser_set_select_multiple; - gtk->gtk_file_chooser_get_current_folder = - fp_gtk_file_chooser_get_current_folder; - gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; - gtk->gtk_g_slist_length = fp_gtk_g_slist_length; - gtk->g_signal_connect_data = fp_g_signal_connect_data; - gtk->gtk_widget_show = fp_gtk_widget_show; - gtk->gtk_main = fp_gtk_main; - gtk->gtk_main_level = fp_gtk_main_level; - gtk->g_path_get_dirname = fp_g_path_get_dirname; - gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid; - gtk->gtk_widget_destroy = fp_gtk_widget_destroy; - gtk->gtk_window_present = fp_gtk_window_present; - gtk->gtk_window_move = fp_gtk_window_move; - gtk->gtk_window_resize = fp_gtk_window_resize; - gtk->get_window = >k2_get_window; - - gtk->g_object_unref = fp_g_object_unref; - gtk->g_list_append = fp_g_list_append; - gtk->g_list_free = fp_g_list_free; - gtk->g_list_free_full = fp_g_list_free_full; -} diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h deleted file mode 100644 index 8075d4f419f..00000000000 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -#ifdef HEADLESS - #error This file should not be included in headless library -#endif - -#ifndef _GTK2_INTERFACE_H -#define _GTK2_INTERFACE_H - -#include -#include -#include -#include "gtk_interface.h" - -#define GTK_HAS_FOCUS (1 << 12) -#define GTK_HAS_DEFAULT (1 << 14) - -typedef enum -{ - GTK_WINDOW_TOPLEVEL, - GTK_WINDOW_POPUP -} GtkWindowType; - -typedef enum -{ - G_PARAM_READABLE = 1 << 0, - G_PARAM_WRITABLE = 1 << 1, - G_PARAM_CONSTRUCT = 1 << 2, - G_PARAM_CONSTRUCT_ONLY = 1 << 3, - G_PARAM_LAX_VALIDATION = 1 << 4, - G_PARAM_PRIVATE = 1 << 5 -} GParamFlags; - -/* We define all structure pointers to be void* */ -typedef void GVfs; - -typedef void GdkColormap; -typedef void GdkDrawable; -typedef void GdkGC; -typedef void GdkPixmap; - -typedef void GtkFixed; -typedef void GtkMenuItem; -typedef void GtkMenuShell; -typedef void GtkWidgetClass; -typedef void PangoFontDescription; -typedef void GtkSettings; - -/* Some real structures */ -typedef struct -{ - guint32 pixel; - guint16 red; - guint16 green; - guint16 blue; -} GdkColor; - -typedef struct { - gint fd; - gushort events; - gushort revents; -} GPollFD; - -typedef struct { - gint x; - gint y; - gint width; - gint height; -} GtkAllocation; - -typedef struct { - gint width; - gint height; -} GtkRequisition; - -typedef struct { - GtkWidgetClass *g_class; -} GTypeInstance; - -typedef struct { - gint left; - gint right; - gint top; - gint bottom; -} GtkBorder; - -/****************************************************** - * FIXME: it is more safe to include gtk headers for - * the precise type definition of GType and other - * structures. This is a place where getting rid of gtk - * headers may be dangerous. - ******************************************************/ - -typedef struct -{ - GType g_type; - - union { - gint v_int; - guint v_uint; - glong v_long; - gulong v_ulong; - gint64 v_int64; - guint64 v_uint64; - gfloat v_float; - gdouble v_double; - gpointer v_pointer; - } data[2]; -} GValue; - -typedef struct -{ - GTypeInstance g_type_instance; - - gchar *name; - GParamFlags flags; - GType value_type; - GType owner_type; -} GParamSpec; - -typedef struct { - GTypeInstance g_type_instance; - guint ref_count; - void *qdata; -} GObject; - -typedef struct { - GObject parent_instance; - guint32 flags; -} GtkObject; - -typedef struct -{ - GObject parent_instance; - - GdkColor fg[5]; - GdkColor bg[5]; - GdkColor light[5]; - GdkColor dark[5]; - GdkColor mid[5]; - GdkColor text[5]; - GdkColor base[5]; - GdkColor text_aa[5]; /* Halfway between text/base */ - - GdkColor black; - GdkColor white; - PangoFontDescription *font_desc; - - gint xthickness; - gint ythickness; - - GdkGC *fg_gc[5]; - GdkGC *bg_gc[5]; - GdkGC *light_gc[5]; - GdkGC *dark_gc[5]; - GdkGC *mid_gc[5]; - GdkGC *text_gc[5]; - GdkGC *base_gc[5]; - GdkGC *text_aa_gc[5]; - GdkGC *black_gc; - GdkGC *white_gc; - - GdkPixmap *bg_pixmap[5]; -} GtkStyle; - -typedef struct _GtkWidget GtkWidget; -struct _GtkWidget -{ - GtkObject object; - guint16 private_flags; - guint8 state; - guint8 saved_state; - gchar *name; - GtkStyle *style; - GtkRequisition requisition; - GtkAllocation allocation; - GdkWindow *window; - GtkWidget *parent; -}; - -typedef struct -{ - GtkWidget widget; - - gfloat xalign; - gfloat yalign; - - guint16 xpad; - guint16 ypad; -} GtkMisc; - -typedef struct { - GtkWidget widget; - GtkWidget *focus_child; - guint border_width : 16; - guint need_resize : 1; - guint resize_mode : 2; - guint reallocate_redraws : 1; - guint has_focus_chain : 1; -} GtkContainer; - -typedef struct { - GtkContainer container; - GtkWidget *child; -} GtkBin; - -typedef struct { - GtkBin bin; - GdkWindow *event_window; - gchar *label_text; - guint activate_timeout; - guint constructed : 1; - guint in_button : 1; - guint button_down : 1; - guint relief : 2; - guint use_underline : 1; - guint use_stock : 1; - guint depressed : 1; - guint depress_on_activate : 1; - guint focus_on_click : 1; -} GtkButton; - -typedef struct { - GtkButton button; - guint active : 1; - guint draw_indicator : 1; - guint inconsistent : 1; -} GtkToggleButton; - -typedef struct _GtkAdjustment GtkAdjustment; -struct _GtkAdjustment -{ - GtkObject parent_instance; - - gdouble lower; - gdouble upper; - gdouble value; - gdouble step_increment; - gdouble page_increment; - gdouble page_size; -}; - -typedef enum -{ - GTK_UPDATE_CONTINUOUS, - GTK_UPDATE_DISCONTINUOUS, - GTK_UPDATE_DELAYED -} GtkUpdateType; - -typedef struct _GtkRange GtkRange; -struct _GtkRange -{ - GtkWidget widget; - GtkAdjustment *adjustment; - GtkUpdateType update_policy; - guint inverted : 1; - /*< protected >*/ - guint flippable : 1; - guint has_stepper_a : 1; - guint has_stepper_b : 1; - guint has_stepper_c : 1; - guint has_stepper_d : 1; - guint need_recalc : 1; - guint slider_size_fixed : 1; - gint min_slider_size; - GtkOrientation orientation; - GdkRectangle range_rect; - gint slider_start, slider_end; - gint round_digits; - /*< private >*/ - guint trough_click_forward : 1; - guint update_pending : 1; - /*GtkRangeLayout * */ void *layout; - /*GtkRangeStepTimer * */ void* timer; - gint slide_initial_slider_position; - gint slide_initial_coordinate; - guint update_timeout_id; - GdkWindow *event_window; -}; - -typedef struct _GtkProgressBar GtkProgressBar; - -typedef enum -{ - GTK_PROGRESS_CONTINUOUS, - GTK_PROGRESS_DISCRETE -} GtkProgressBarStyle; - -typedef enum -{ - GTK_PROGRESS_LEFT_TO_RIGHT, - GTK_PROGRESS_RIGHT_TO_LEFT, - GTK_PROGRESS_BOTTOM_TO_TOP, - GTK_PROGRESS_TOP_TO_BOTTOM -} GtkProgressBarOrientation; - -typedef struct _GtkProgress GtkProgress; - -struct _GtkProgress -{ - GtkWidget widget; - GtkAdjustment *adjustment; - GdkPixmap *offscreen_pixmap; - gchar *format; - gfloat x_align; - gfloat y_align; - guint show_text : 1; - guint activity_mode : 1; - guint use_text_format : 1; -}; - -struct _GtkProgressBar -{ - GtkProgress progress; - GtkProgressBarStyle bar_style; - GtkProgressBarOrientation orientation; - guint blocks; - gint in_block; - gint activity_pos; - guint activity_step; - guint activity_blocks; - gdouble pulse_fraction; - guint activity_dir : 1; - guint ellipsize : 3; -}; - -/** - * Returns : - * NULL if the GLib library is compatible with the given version, or a string - * describing the version mismatch. - * Please note that the glib_check_version() is available since 2.6, - * so you should use GLIB_CHECK_VERSION macro instead. - */ -static gchar* (*fp_glib_check_version)(guint required_major, guint required_minor, - guint required_micro); - -/** - * Returns : - * TRUE if the GLib library is compatible with the given version - */ -#define GLIB_CHECK_VERSION(major, minor, micro) \ - (fp_glib_check_version && fp_glib_check_version(major, minor, micro) == NULL) - -/** - * Returns : - * NULL if the GTK+ library is compatible with the given version, or a string - * describing the version mismatch. - */ -static gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor, - guint required_micro); - -static void gtk2_init(GtkApi* gtk); - -static void (*fp_g_free)(gpointer mem); -static void (*fp_g_object_unref)(gpointer object); -static GdkWindow *(*fp_gdk_get_default_root_window) (void); - -static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf); -static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf); -static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf); -static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf); -static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error); -static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf); - -static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest, - GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y, - int dest_x, int dest_y, int width, int height); -static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src, - int dest_width, int dest_heigh, GdkInterpType interp_type); - - -static void (*fp_gtk_widget_destroy)(void *widget); -static void (*fp_gtk_window_present)(GtkWindow *window); -static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y); -static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height); - -/** - * Function Pointers for GtkFileChooser - */ -static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser); -static void (*fp_gtk_widget_hide)(void *widget); -static void (*fp_gtk_main_quit)(void); -static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title, - GtkWindow *parent, GtkFileChooserAction action, - const gchar *first_button_text, ...); -static gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, - const gchar *filename); -static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser, - const char *filename); -static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, - const gchar *name); -static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter, - GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data, - GDestroyNotify notify); -static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, - GtkFileFilter *filter); -static GType (*fp_gtk_file_chooser_get_type)(void); -static GtkFileFilter* (*fp_gtk_file_filter_new)(void); -static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)( - GtkFileChooser *chooser, gboolean do_overwrite_confirmation); -static void (*fp_gtk_file_chooser_set_select_multiple)( - GtkFileChooser *chooser, gboolean select_multiple); -static gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); -static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); -static guint (*fp_gtk_g_slist_length)(GSList *list); -static gulong (*fp_g_signal_connect_data)(gpointer instance, - const gchar *detailed_signal, GCallback c_handler, gpointer data, - GClosureNotify destroy_data, GConnectFlags connect_flags); -static void (*fp_gtk_widget_show)(void *widget); -static void (*fp_gtk_main)(void); -static guint (*fp_gtk_main_level)(void); -static gchar* (*fp_g_path_get_dirname) (const gchar *file_name); -static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable); - -static GList* (*fp_g_list_append) (GList *list, gpointer data); -static void (*fp_g_list_free) (GList *list); -static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func); - -static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri, - guint32 timestamp, GError **error); - -#endif /* !_GTK2_INTERFACE_H */ diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c index c8573ed3fbf..fcf84948c66 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,8 @@ #include "jvm_md.h" #include "gtk_interface.h" -GtkApi* gtk2_load(JNIEnv *env, const char* lib_name); GtkApi* gtk3_load(JNIEnv *env, const char* lib_name); -gboolean gtk2_check(const char* lib_name, gboolean load); gboolean gtk3_check(const char* lib_name, gboolean load); GtkApi *gtk; @@ -56,13 +54,6 @@ static GtkLib gtk_libs[] = { >k3_load, >k3_check }, - { - GTK_2, - JNI_LIB_NAME("gtk-x11-2.0"), - VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0"), - >k2_load, - >k2_check - } }; static GtkLib** get_libs_order(GtkVersion version) { diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c index e2f4ea31d2e..6884b939ae7 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -675,7 +675,6 @@ static gboolean isAllDataReady() { static void *pipewire_libhandle = NULL; -//glib_version_2_68 false for gtk2, as it comes from gtk3_interface.c extern gboolean glib_version_2_68; diff --git a/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java b/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java index d2e460d4a16..3d530178a8a 100644 --- a/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java +++ b/test/jdk/java/awt/Gtk/GtkVersionTest/GtkVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,8 +45,9 @@ public static void main(String[] args) { public static void main(String[] args) throws Exception { test(null, "3"); - test("2", "2"); - test("2.2", "2"); +// GTK 2 is removed, but the test can still be useful. +// test("2", "2"); +// test("2.2", "2"); test("3", "3"); } diff --git a/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java b/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java index 1f6298a2a61..155933404e8 100644 --- a/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java +++ b/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, JetBrains s.r.o.. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -41,10 +41,9 @@ * @test * @key headful * @bug 8280861 - * @summary Verifies Robot screen capture capabilities with different + * @summary Verifies Robot screen capture capabilities with available * Gtk backends and presence of UI scaling * @requires os.family == "linux" - * @run main/othervm -Djdk.gtk.version=2 -Dsun.java2d.uiScale=1 ScreenCaptureGtkTest * @run main/othervm -Djdk.gtk.version=3 -Dsun.java2d.uiScale=1 ScreenCaptureGtkTest */ @@ -53,12 +52,6 @@ public class ScreenCaptureGtkTest { Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED}; public static void main(String[] args) throws Exception { - if ("2".equals(System.getProperty("jdk.gtk.version")) - && System.getenv("WAYLAND_DISPLAY") != null) { - // screen capture is not supported with gtk2 on Wayland - return; - } - final int topOffset = 50; final int leftOffset = 50; diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java index a8d460bc48e..906126071ff 100644 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java +++ b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ @bug 8156121 @key headful @requires os.family == "linux" - @run main/othervm -Djdk.gtk.version=2 DemandGTK @run main/othervm -Djdk.gtk.version=3 DemandGTK */ diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh deleted file mode 100644 index eddae8748a7..00000000000 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/ksh -p - -# -# Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# @test -# @summary Try to force GTK2. We must bail out to GTK3 (if any) if no 2 available. -# -# @key headful -# @bug 8156128 8212903 -# @compile ProvokeGTK.java -# @requires os.family == "linux" -# @run shell/timeout=400 DemandGTK2.sh - -# -# Note that we depend on -# strace in the PATH -# /sbin/ldconfig (which may be not in PATH) -# It is true for OEL 7 and Ubuntu 14, 16 -# but may fail in future. Save tomorrow for tomorrow. -# -# Read DemandGTK2.txt how to prepare GTK2-less machine. -# - -which strace -if [ $? -ne 0 ] -then - echo "Please provide strace: \"which strace\" failed." - exit 1 -fi - -HAVE_2=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 | wc -l` -HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` - - -if [ "${HAVE_2}" = "0" ] -then - - if [ "${HAVE_3}" = "0" ] - then - echo "Neither GTK2 nor GTK3 found: system misconfiguration. Exit." - exit 1 - fi - echo "No GTK 2 library found: we should bail out to 3" - strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK - EXECRES=$? - grep 'libgtk-3.*=\ *[0-9]*$' strace.log > logg -else - echo "There is GTK 2 library: we should use it" - strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=2 ProvokeGTK - EXECRES=$? - grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg -fi - -if [ ${EXECRES} -ne 0 ] -then - echo "java execution failed for unknown reason, see logs" - exit 2 -fi - -cat logg -if [ -s logg ] -then - echo "Success." - exit 0 -else - echo "Failed. Examine logs." - exit 3 -fi - - diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt deleted file mode 100644 index 7313e3ee4a7..00000000000 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK2.txt +++ /dev/null @@ -1,36 +0,0 @@ -How to prepare an Ubuntu machine for GTK-2-less test run. - -The test DemandGTK2.sh should work well without GTK-2 switching to version 3 -if there's no GTK-2 library available. -At the moment, it's not easy to find a system with GTK-3 and without GTK-2: -many programs still depend on version 2. -We can, however, rename GTK-2 library for a single test run and then restore -it back. - -(1) Find GTK2 library: run - /sbin/ldconfig -v 2>/dev/null | grep libgtk-x11-2 - -It will output one or two lines like -libgtk-x11-2.0.so.0 -> libgtk-x11-2.0.so.0.2400.23 -Search for the target of that symlink for instance with locate: -locate libgtk-x11-2.0.so.0.2400.23 -Finally, you'll find the libraries. On my current machine they are -/usr/lib/i386-linux-gnu/libgtk-x11-2.0.so.0.2400.23 -/usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 - -I'm running 64-bit JDK and need to tamper with x86_64 copy only. - -(2) Find running programs depending on this library. They probably would crash -if you rename it. Stop them for this test run. -That said, I'm afraid it would be impossible to do on a system older than Ubuntu 16.04. -On my Ubuntu 16.04 I have only hud-service using this library, and that's OK, it will restart -after a crash, if any. -To find these programs, run -lsof /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 - -(3) Now, -sudo mv /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 -jtreg DemandGTK2.sh -sudo mv /usr/lib/x86_64-linux-gnu/bak.libgtk-x11-2.0.so.0.2400.23 /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0.2400.23 - -Needless to say, you should substitute your own library path and however you run jtreg. diff --git a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh index bb00493c862..2383cc82851 100644 --- a/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh +++ b/test/jdk/javax/swing/LookAndFeel/8145547/DemandGTK3.sh @@ -1,7 +1,7 @@ #!/bin/ksh -p # -# Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ # @test -# @summary Try to force GTK3. We must bail out to GTK2 if no 3 available. +# @summary Try to force GTK3. # # @key headful # @bug 8156128 8212903 @@ -53,11 +53,8 @@ HAVE_3=`/sbin/ldconfig -v 2>/dev/null | grep libgtk-3.so | wc -l` if [ "${HAVE_3}" = "0" ] then - - echo "No GTK 3 library found: we should bail out to 2" - strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK - EXECRES=$? - grep 'libgtk-x11.*=\ *[0-9]*$' strace.log > logg + echo "No GTK 3 library found, do nothing" + exit 0 else echo "There is GTK 3 library: we should use it" strace -o strace.log -fe open,openat ${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} -Djdk.gtk.version=3 ProvokeGTK From ddbd7a78f191462695ecbeeef7fd6312e322b15a Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 8 Aug 2024 10:53:23 +0000 Subject: [PATCH 07/84] 8337320: Update ProblemList.txt with tests known to fail on XWayland Reviewed-by: prr --- test/jdk/ProblemList.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 84c7a7d855f..3b8421eb9cc 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -473,6 +473,12 @@ java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 m # This test fails on macOS 14 java/awt/Choice/SelectNewItemTest/SelectNewItemTest.java 8324782 macosx-all +# Wayland related + +java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8332158 linux-x64 +java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64 +java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64 + ############################################################################ # jdk_beans From 4b740d87ee50ba49305add4aae6490bebb6963ba Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 8 Aug 2024 10:57:43 +0000 Subject: [PATCH 08/84] 8225209: jdk/jfr/event/compiler/TestCodeSweeper.java fails Reviewed-by: mgronlun --- test/jdk/ProblemList.txt | 1 - .../jfr/event/compiler/TestCodeSweeper.java | 56 +++++++++++++------ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 3b8421eb9cc..8aedbc77931 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -744,7 +744,6 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr -jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 diff --git a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java index cb2a3f41b55..df95af5b9be 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,11 @@ import java.lang.reflect.Method; import java.time.Instant; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import jdk.jfr.Recording; +import jdk.jfr.Event; +import jdk.jfr.consumer.RecordingStream; import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.Asserts; import jdk.test.lib.jfr.EventNames; @@ -39,7 +41,7 @@ import jdk.test.whitebox.code.CodeBlob; /** - * Test for events: vm/code_cache/full vm/compiler/failure + * Test for events: jdk.CodeCacheFull jdk.CompilationFailure * * We verify that we should get at least one of each of the events listed above. * @@ -58,13 +60,15 @@ */ public class TestCodeSweeper { + static class ProvocationEvent extends Event { + } private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final int COMP_LEVEL_SIMPLE = 1; private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; private static final int SIZE = 1; private static final String METHOD_NAME = "verifyFullEvent"; - private static final String pathFull = EventNames.CodeCacheFull; - private static final String pathFailure = EventNames.CompilationFailure; + private static final String EVENT_CODE_CACHE_FULL = EventNames.CodeCacheFull; + private static final String EVENT_COMPILATION_FAILURE = EventNames.CompilationFailure; public static final long SEGMENT_SIZE = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheSegmentSize"); public static final long MIN_BLOCK_LENGTH = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheMinBlockLength"); public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH; @@ -77,26 +81,41 @@ public static void main(String[] args) throws Throwable { System.out.println("This test will warn that the code cache is full."); System.out.println("That is expected and is the purpose of the test."); System.out.println("************************************************"); - - Recording r = new Recording(); - r.enable(pathFull); - r.enable(pathFailure); - r.start(); - provokeEvents(); - r.stop(); + List events = Collections.synchronizedList(new ArrayList<>()); + try (RecordingStream rs = new RecordingStream()) { + rs.setReuse(false); + rs.enable(EVENT_CODE_CACHE_FULL); + rs.enable(EVENT_COMPILATION_FAILURE); + rs.onEvent(EVENT_CODE_CACHE_FULL, events::add); + rs.onEvent(EVENT_COMPILATION_FAILURE, events::add); + rs.onEvent(ProvocationEvent.class.getName(), e -> { + if (!events.isEmpty()) { + rs.close(); + return; + } + // Retry if CodeCacheFull or CompilationFailure events weren't provoked + try { + provokeEvents(); + } catch (Exception ex) { + ex.printStackTrace(); + rs.close(); + } + }); + rs.startAsync(); + provokeEvents(); + rs.awaitTermination(); + } int countEventFull = 0; int countEventFailure = 0; - - List events = Events.fromRecording(r); Events.hasEvents(events); - for (RecordedEvent event : events) { + for (RecordedEvent event : new ArrayList<>(events)) { switch (event.getEventType().getName()) { - case pathFull: + case EVENT_CODE_CACHE_FULL: countEventFull++; verifyFullEvent(event); break; - case pathFailure: + case EVENT_COMPILATION_FAILURE: countEventFailure++; verifyFailureEvent(event); break; @@ -115,6 +134,8 @@ private static boolean canAllocate(double size, long maxSize, MemoryPoolMXBean b } private static void provokeEvents() throws NoSuchMethodException, InterruptedException { + System.out.println("provokeEvents()"); + ProvocationEvent provocationEvent = new ProvocationEvent(); // Prepare for later, since we don't want to trigger any compilation // setting this up. Method method = TestCodeSweeper.class.getDeclaredMethod(METHOD_NAME, new Class[] { RecordedEvent.class }); @@ -159,6 +180,7 @@ private static void provokeEvents() throws NoSuchMethodException, InterruptedExc for (Long blob : blobs) { WHITE_BOX.freeCodeBlob(blob); } + provocationEvent.commit(); } private static void verifyFullEvent(RecordedEvent event) throws Throwable { From 6a9a867d645b8fe86f4ca2b04a43bf5aa8f9d487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Aug 2024 14:38:46 +0000 Subject: [PATCH 09/84] 8337994: [REDO] Native memory leak when not recording any events Reviewed-by: egahlin --- .../share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp | 9 +++++++++ .../share/jfr/recorder/service/jfrRecorderService.cpp | 6 +----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index 203ec3a3ec4..279b871d818 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -883,6 +883,15 @@ static void do_clds(CldWriter& cldw) { ModuleCldWriter mcw(&cldw); KlassAndModuleCldWriter kmcw(&kcw, &mcw); _artifacts->iterate_klasses(kmcw); + if (is_initial_typeset_for_chunk()) { + CldPtr bootloader = get_cld(Universe::boolArrayKlass()); + assert(bootloader != nullptr, "invariant"); + if (IS_NOT_SERIALIZED(bootloader)) { + write__cld(_writer, bootloader); + assert(IS_SERIALIZED(bootloader), "invariant"); + cldw.add(1); + } + } _artifacts->tally(cldw); } diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index fc2043a4d92..0395b711c65 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -639,11 +639,7 @@ static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) { size_t JfrRecorderService::flush() { size_t total_elements = flush_metadata(_chunkwriter); - const size_t storage_elements = flush_storage(_storage, _chunkwriter); - if (0 == storage_elements) { - return total_elements; - } - total_elements += storage_elements; + total_elements = flush_storage(_storage, _chunkwriter); if (_string_pool.is_modified()) { total_elements += flush_stringpool(_string_pool, _chunkwriter); } From 78773b1769922611318243b6680d59518ed4e015 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 8 Aug 2024 15:52:17 +0000 Subject: [PATCH 10/84] 8338015: Fix "Java Java" typo in package info file of java.lang.classfile Reviewed-by: jiefu, jpai, liach --- .../share/classes/java/lang/classfile/package-info.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/classfile/package-info.java b/src/java.base/share/classes/java/lang/classfile/package-info.java index b5991b0e951..921cf9e1a34 100644 --- a/src/java.base/share/classes/java/lang/classfile/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/package-info.java @@ -26,8 +26,8 @@ /** *

Provides classfile parsing, generation, and transformation library.

* The {@code java.lang.classfile} package contains classes for reading, writing, and - * modifying Java class files, as specified in Chapter {@jvms 4} of the Java - * Java Virtual Machine Specification. + * modifying Java class files, as specified in Chapter {@jvms 4} of the + * Java Virtual Machine Specification. * *

Reading classfiles

* The main class for reading classfiles is {@link java.lang.classfile.ClassModel}; we From 9695f09581bac856ad97943cca15c65dc21d2adf Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 8 Aug 2024 16:11:08 +0000 Subject: [PATCH 11/84] 8337683: Fix -Wconversion problem with arrayOop.hpp Reviewed-by: stefank, dholmes --- src/hotspot/share/oops/arrayOop.hpp | 18 +++++++++--------- src/hotspot/share/runtime/atomic.hpp | 5 +++-- src/hotspot/share/utilities/byteswap.hpp | 3 ++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/oops/arrayOop.hpp b/src/hotspot/share/oops/arrayOop.hpp index 0aa26500bd8..1ca8a9530a4 100644 --- a/src/hotspot/share/oops/arrayOop.hpp +++ b/src/hotspot/share/oops/arrayOop.hpp @@ -68,10 +68,10 @@ class arrayOopDesc : public oopDesc { // The header is considered the oop part of this type plus the length. // This is not equivalent to sizeof(arrayOopDesc) which should not appear in the code. static int header_size_in_bytes() { - size_t hs = length_offset_in_bytes() + sizeof(int); + int hs = length_offset_in_bytes() + (int)sizeof(int); #ifdef ASSERT // make sure it isn't called before UseCompressedOops is initialized. - static size_t arrayoopdesc_hs = 0; + static int arrayoopdesc_hs = 0; if (arrayoopdesc_hs == 0) arrayoopdesc_hs = hs; assert(arrayoopdesc_hs == hs, "header size can't change"); #endif // ASSERT @@ -83,13 +83,13 @@ class arrayOopDesc : public oopDesc { // it occupies the second half of the _klass field in oopDesc. static int length_offset_in_bytes() { return UseCompressedClassPointers ? klass_gap_offset_in_bytes() : - sizeof(arrayOopDesc); + (int)sizeof(arrayOopDesc); } // Returns the offset of the first element. static int base_offset_in_bytes(BasicType type) { - size_t hs = header_size_in_bytes(); - return (int)(element_type_should_be_aligned(type) ? align_up(hs, BytesPerLong) : hs); + int hs = header_size_in_bytes(); + return element_type_should_be_aligned(type) ? align_up(hs, BytesPerLong) : hs; } // Returns the address of the first element. The elements in the array will not @@ -134,14 +134,14 @@ class arrayOopDesc : public oopDesc { assert(type < T_CONFLICT, "wrong type"); assert(type2aelembytes(type) != 0, "wrong type"); - size_t hdr_size_in_bytes = base_offset_in_bytes(type); + int hdr_size_in_bytes = base_offset_in_bytes(type); // This is rounded-up and may overlap with the first array elements. - size_t hdr_size_in_words = align_up(hdr_size_in_bytes, HeapWordSize) / HeapWordSize; + int hdr_size_in_words = align_up(hdr_size_in_bytes, HeapWordSize) / HeapWordSize; const size_t max_element_words_per_size_t = - align_down((SIZE_MAX/HeapWordSize - hdr_size_in_words), MinObjAlignment); + align_down((SIZE_MAX/HeapWordSize - (size_t)hdr_size_in_words), MinObjAlignment); const size_t max_elements_per_size_t = - HeapWordSize * max_element_words_per_size_t / type2aelembytes(type); + HeapWordSize * max_element_words_per_size_t / (size_t)type2aelembytes(type); if ((size_t)max_jint < max_elements_per_size_t) { // It should be ok to return max_jint here, but parts of the code // (CollectedHeap, Klass::oop_oop_iterate(), and more) uses an int for diff --git a/src/hotspot/share/runtime/atomic.hpp b/src/hotspot/share/runtime/atomic.hpp index 399a78fd3fc..bf198b5f562 100644 --- a/src/hotspot/share/runtime/atomic.hpp +++ b/src/hotspot/share/runtime/atomic.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "runtime/orderAccess.hpp" #include "utilities/align.hpp" #include "utilities/bytes.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/macros.hpp" #include @@ -1118,7 +1119,7 @@ inline T Atomic::CmpxchgByteUsingInt::operator()(T volatile* dest, uint8_t canon_compare_value = compare_value; volatile uint32_t* aligned_dest = reinterpret_cast(align_down(dest, sizeof(uint32_t))); - size_t offset = pointer_delta(dest, aligned_dest, 1); + uint32_t offset = checked_cast(pointer_delta(dest, aligned_dest, 1)); uint32_t idx = (Endian::NATIVE == Endian::BIG) ? (sizeof(uint32_t) - 1 - offset) diff --git a/src/hotspot/share/utilities/byteswap.hpp b/src/hotspot/share/utilities/byteswap.hpp index fba0775cf49..9c3b53630b3 100644 --- a/src/hotspot/share/utilities/byteswap.hpp +++ b/src/hotspot/share/utilities/byteswap.hpp @@ -26,6 +26,7 @@ #define SHARE_UTILITIES_BYTESWAP_HPP #include "metaprogramming/enableIf.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/globalDefinitions.hpp" #include @@ -63,7 +64,7 @@ struct ByteswapFallbackImpl; template struct ByteswapFallbackImpl { inline constexpr uint16_t operator()(uint16_t x) const { - return (((x & UINT16_C(0x00ff)) << 8) | ((x & UINT16_C(0xff00)) >> 8)); + return checked_cast(((x & UINT16_C(0x00ff)) << 8) | ((x & UINT16_C(0xff00)) >> 8)); } }; From 53c9f037fb2805aab5ab9729166ce7d5bc7a77f9 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Thu, 8 Aug 2024 16:31:02 +0000 Subject: [PATCH 12/84] 8336849: Remove .llvm_addrsig section from JDK/VM static libraries (.a files) Reviewed-by: ihse --- make/common/native/Link.gmk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/make/common/native/Link.gmk b/make/common/native/Link.gmk index 2090218ffbb..ca03c6ee6b1 100644 --- a/make/common/native/Link.gmk +++ b/make/common/native/Link.gmk @@ -109,6 +109,11 @@ define CreateStaticLibrary $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ $$($1_LD) $(LDFLAGS_CXX_PARTIAL_LINKING) $$($1_SYSROOT_LDFLAGS) \ -o $$($1_TARGET_RELOCATABLE) $$($1_LD_OBJ_ARG)) + # 'ld -r' might invalidate the .llvm_addrsig section, and this will cause subsequent + # calls to lld (with '-Wl,--icf=safe') to fail when linking with this library, so + # remove that section. + $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_objcopy_remove_llvm_addrsig_section, \ + $$($1_OBJCOPY) --remove-section=.llvm_addrsig $$($1_TARGET_RELOCATABLE)) endif $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_ar, \ $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ From bfb75b96266f4c5840e2edea13f9aa2c801518cf Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 8 Aug 2024 16:53:38 +0000 Subject: [PATCH 13/84] 8336926: jdk/internal/util/ReferencedKeyTest.java can fail with ConcurrentModificationException Reviewed-by: bpb, shade, dfuchs --- .../jdk/internal/util/ReferencedKeyMap.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java index 9c364cd7813..810d43ae38a 100644 --- a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java +++ b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -219,8 +219,14 @@ public boolean containsValue(Object value) { @Override public V get(Object key) { - Objects.requireNonNull(key, "key must not be null"); removeStaleReferences(); + return getNoCheckStale(key); + } + + // Internal get(key) without removing stale references that would modify the keyset. + // Use when iterating or streaming over the keys to avoid ConcurrentModificationException. + private V getNoCheckStale(Object key) { + Objects.requireNonNull(key, "key must not be null"); return map.get(lookupKey(key)); } @@ -291,7 +297,7 @@ public Collection values() { public Set> entrySet() { removeStaleReferences(); return filterKeySet() - .map(k -> new AbstractMap.SimpleEntry<>(k, get(k))) + .map(k -> new AbstractMap.SimpleEntry<>(k, getNoCheckStale(k))) .collect(Collectors.toSet()); } @@ -335,7 +341,7 @@ public V replace(K key, V value) { public String toString() { removeStaleReferences(); return filterKeySet() - .map(k -> k + "=" + get(k)) + .map(k -> k + "=" + getNoCheckStale(k)) .collect(Collectors.joining(", ", "{", "}")); } From e7a0b5b09bcfcd8b09667e51ec588e206f0652ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Aug 2024 18:45:11 +0000 Subject: [PATCH 14/84] 8334780: Crash: assert(h_array_list.not_null()) failed: invariant Reviewed-by: egahlin, shade --- src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp index cd476302289..0c2fb0206ec 100644 --- a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp +++ b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp @@ -136,7 +136,9 @@ jobject JdkJfrEvent::get_all_klasses(TRAPS) { transform_klasses_to_local_jni_handles(event_subklasses, THREAD); Handle h_array_list(THREAD, new_java_util_arraylist(THREAD)); - assert(h_array_list.not_null(), "invariant"); + if (h_array_list.is_null()) { + return empty_java_util_arraylist; + } static const char add_method_name[] = "add"; static const char add_method_signature[] = "(Ljava/lang/Object;)Z"; From 9f08a01cb6ebb08f67749aabdff4efaedfaf3228 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Thu, 8 Aug 2024 19:47:50 +0000 Subject: [PATCH 15/84] 8338010: WB_IsFrameDeoptimized miss ResourceMark Reviewed-by: dholmes, shade --- src/hotspot/share/prims/whitebox.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 6ee33a61079..544eeabb5c2 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -799,6 +799,7 @@ WB_END WB_ENTRY(jboolean, WB_IsFrameDeoptimized(JNIEnv* env, jobject o, jint depth)) bool result = false; if (thread->has_last_Java_frame()) { + ResourceMark rm(THREAD); RegisterMap reg_map(thread, RegisterMap::UpdateMap::include, RegisterMap::ProcessFrames::include, From 55c509708e9b89a7609fd41b6e5a271f250bbacd Mon Sep 17 00:00:00 2001 From: Jiawei Tang Date: Fri, 9 Aug 2024 02:29:15 +0000 Subject: [PATCH 16/84] 8337331: crash: pinned virtual thread will lead to jvm crash when running with the javaagent option Reviewed-by: dholmes, sspitsyn --- src/hotspot/share/prims/jvmtiExport.cpp | 10 +-- .../TestPinCaseWithCFLH.java | 77 +++++++++++++++++++ 2 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index f79116f5ebe..95cc54d9313 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -929,9 +929,8 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _cached_class_file_ptr = cache_ptr; _has_been_modified = false; - if (_thread->is_in_any_VTMS_transition()) { - return; // no events should be posted if thread is in any VTMS transition - } + assert(!_thread->is_in_any_VTMS_transition(), "CFLH events are not allowed in any VTMS transition"); + _state = JvmtiExport::get_jvmti_thread_state(_thread); if (_state != nullptr) { _class_being_redefined = _state->get_class_being_redefined(); @@ -1091,8 +1090,9 @@ bool JvmtiExport::post_class_file_load_hook(Symbol* h_name, if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) { return false; } - if (JavaThread::current()->is_in_tmp_VTMS_transition()) { - return false; // skip CFLH events in tmp VTMS transition + + if (JavaThread::current()->is_in_any_VTMS_transition()) { + return false; // no events should be posted if thread is in any VTMS transition } JvmtiClassFileLoadHookPoster poster(h_name, class_loader, diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java new file mode 100644 index 00000000000..02755a0289f --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.security.ProtectionDomain; +import jdk.test.lib.thread.VThreadPinner; + +/* + * @test + * @summary javaagent + tracePinnedThreads will cause jvm crash/ run into deadlock when the virtual thread is pinned + * @library /test/lib + * @requires vm.continuations + * @requires vm.jvmti + * @modules java.base/java.lang:+open + * @compile TestPinCaseWithCFLH.java + * @build jdk.test.lib.Utils + * @run driver jdk.test.lib.util.JavaAgentBuilder + * TestPinCaseWithCFLH TestPinCaseWithCFLH.jar + * @run main/othervm/timeout=100 -Djdk.virtualThreadScheduler.maxPoolSize=1 + * -Djdk.tracePinnedThreads=full --enable-native-access=ALL-UNNAMED + * -javaagent:TestPinCaseWithCFLH.jar TestPinCaseWithCFLH + */ +public class TestPinCaseWithCFLH { + + public static class TestClassFileTransformer implements ClassFileTransformer { + public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, + ProtectionDomain protectionDomain, byte[] classfileBuffer) + throws IllegalClassFormatException { + return classfileBuffer; + } + } + + // Called when agent is loaded at startup + public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { + instrumentation.addTransformer(new TestClassFileTransformer()); + } + + private static int result = 0; + + public static void main(String[] args) throws Exception{ + Thread t1 = Thread.ofVirtual().name("vthread-1").start(() -> { + VThreadPinner.runPinned(() -> { + try { + // try yield, will pin, + // javaagent + tracePinnedThreads should not lead to crash + // (because of the class `PinnedThreadPrinter`) + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + }); + }); + t1.join(); + } + +} \ No newline at end of file From 0c1e9111d226b601236b9826e27ecc67a8b625fb Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Fri, 9 Aug 2024 02:59:37 +0000 Subject: [PATCH 17/84] 8338019: Fix simple -Wzero-as-null-pointer-constant warnings in riscv code Reviewed-by: fyang, mli, luhenry --- src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 2 +- src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 2 +- src/hotspot/cpu/riscv/frame_riscv.cpp | 2 +- src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 798679185d3..3d146b87707 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -542,7 +542,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi insn = &MacroAssembler::sw; break; case T_OBJECT: // fall through case T_ARRAY: - assert(c->as_jobject() == 0, "should be"); + assert(c->as_jobject() == nullptr, "should be"); if (UseCompressedOops && !wide) { insn = &MacroAssembler::sw; } else { diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp index 9fa8939837a..e999b703b3e 100644 --- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -1066,4 +1066,4 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { #undef __ -const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); return 0; } +const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); } diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp index 32825a02c5e..96dca4704ad 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.cpp +++ b/src/hotspot/cpu/riscv/frame_riscv.cpp @@ -269,7 +269,7 @@ void frame::patch_pc(Thread* thread, address pc) { // Either the return address is the original one or we are going to // patch in the same address that's already there. - assert(_pc == pc_old || pc == pc_old || pc_old == 0, "must be"); + assert(_pc == pc_old || pc == pc_old || pc_old == nullptr, "must be"); DEBUG_ONLY(address old_pc = _pc;) *pc_addr = pc; _pc = pc; // must be set before call to get_deopt_original_pc diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index f0357f1cd30..6c9e0986869 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -685,7 +685,7 @@ address NativeJump::jump_destination() const { // load // return -1 if jump to self or to 0 - if ((dest == (address) this) || dest == 0) { + if ((dest == (address) this) || dest == nullptr) { dest = (address) -1; } @@ -714,7 +714,7 @@ address NativeGeneralJump::jump_destination() const { // a general jump // return -1 if jump to self or to 0 - if ((dest == (address) this) || dest == 0) { + if ((dest == (address) this) || dest == nullptr) { dest = (address) -1; } From 9ab8c6b9ba90ffd12600a250c8704571e9feb78d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 9 Aug 2024 05:09:27 +0000 Subject: [PATCH 18/84] 8335130: The test "javax/swing/plaf/synth/ComponentsOrientationSupport/5033822/bug5033822.java" fails because the background color of the tabs is displayed incorrectly. Reviewed-by: achung, psadhukhan --- .../sun/java/swing/plaf/gtk/GTKPainter.java | 34 ++++++++-------- .../swing/plaf/nimbus/SynthPainterImpl.java | 39 ++++++++++--------- .../swing/plaf/synth/SynthTabbedPaneUI.java | 8 +--- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index 4787696a367..ea27a2a6e0d 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -935,25 +935,27 @@ public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int tabIndex) { - Region id = context.getRegion(); - int state = context.getComponentState(); - int gtkState = ((state & SynthConstants.SELECTED) != 0 ? - SynthConstants.ENABLED : SynthConstants.PRESSED); JTabbedPane pane = (JTabbedPane)context.getComponent(); - int placement = pane.getTabPlacement(); + if (UIManager.getBoolean("TabbedPane.tabsOpaque") || pane.isOpaque()) { + Region id = context.getRegion(); + int state = context.getComponentState(); + int gtkState = ((state & SynthConstants.SELECTED) != 0 ? + SynthConstants.ENABLED : SynthConstants.PRESSED); + int placement = pane.getTabPlacement(); - // Fill the tab rect area - g.fillRect(x, y, w, h); + // Fill the tab rect area + g.fillRect(x, y, w, h); - synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, - id, gtkState, placement, tabIndex)) { - PositionType side = POSITIONS[placement - 1]; - ENGINE.startPainting(g, x, y, w, h, - id, gtkState, placement, tabIndex); - ENGINE.paintExtension(g, context, id, gtkState, - ShadowType.OUT, "tab", x, y, w, h, side, tabIndex); - ENGINE.finishPainting(); + synchronized (UNIXToolkit.GTK_LOCK) { + if (!ENGINE.paintCachedImage(g, x, y, w, h, + id, gtkState, placement, tabIndex)) { + PositionType side = POSITIONS[placement - 1]; + ENGINE.startPainting(g, x, y, w, h, + id, gtkState, placement, tabIndex); + ENGINE.paintExtension(g, context, id, gtkState, + ShadowType.OUT, "tab", x, y, w, h, side, tabIndex); + ENGINE.finishPainting(); + } } } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java index c990c968ff6..9dfd422f6dd 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java @@ -2098,24 +2098,27 @@ public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int tabIndex, int orientation) { - if (orientation == JTabbedPane.LEFT) { - AffineTransform transform = new AffineTransform(); - transform.scale(-1, 1); - transform.rotate(Math.toRadians(90)); - paintBackground(context, g, y, x, h, w, transform); - } else if (orientation == JTabbedPane.RIGHT) { - AffineTransform transform = new AffineTransform(); - transform.rotate(Math.toRadians(90)); - transform.translate(0, -(x + w)); - paintBackground(context, g, y, 0, h, w, transform); - } else if (orientation == JTabbedPane.BOTTOM) { - AffineTransform transform = new AffineTransform(); - transform.translate(x,y); - transform.scale(1, -1); - transform.translate(0,-h); - paintBackground(context, g, 0, 0, w, h, transform); - } else { - paintBackground(context, g, x, y, w, h, null); + JTabbedPane pane = (JTabbedPane)context.getComponent(); + if (UIManager.getBoolean("TabbedPane.tabsOpaque") || pane.isOpaque()) { + if (orientation == JTabbedPane.LEFT) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBackground(context, g, y, x, h, w, transform); + } else if (orientation == JTabbedPane.RIGHT) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintBackground(context, g, y, 0, h, w, transform); + } else if (orientation == JTabbedPane.BOTTOM) { + AffineTransform transform = new AffineTransform(); + transform.translate(x, y); + transform.scale(1, -1); + transform.translate(0, -h); + paintBackground(context, g, 0, 0, w, h, transform); + } else { + paintBackground(context, g, x, y, w, h, null); + } } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java index 837c4d8298f..3378ef9e8b3 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java @@ -127,7 +127,6 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI // Background color for unselected tabs private Color unselectedBackground; private boolean contentOpaque = true; - private boolean tabsOpaque = true; /** * @@ -156,7 +155,6 @@ private boolean scrollableTabLayoutEnabled() { protected void installDefaults() { selectColor = UIManager.getColor("TabbedPane.selected"); contentOpaque = UIManager.getBoolean("TabbedPane.contentOpaque"); - tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque"); unselectedBackground = UIManager.getColor("TabbedPane.unselectedBackground"); updateStyle(tabPane); } @@ -655,10 +653,8 @@ private void paintTab(SynthContext ss, Graphics g, g.setColor(getUnselectedBackgroundAt(tabIndex)); } - if (tabsOpaque || tabPane.isOpaque()) { - tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g, - x, y, width, height, tabIndex, placement); - } + tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g, + x, y, width, height, tabIndex, placement); tabContext.getPainter().paintTabbedPaneTabBorder(tabContext, g, x, y, width, height, tabIndex, placement); From 00aac4097abd3c5e6144734cfd44228bc31892fb Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 9 Aug 2024 06:26:22 +0000 Subject: [PATCH 19/84] 8338058: map_or_reserve_memory_aligned Windows enhance remap assertion Reviewed-by: mdoerr, clanger --- src/hotspot/os/windows/os_windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 1cc7d9aa33a..65ba13b0d9e 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3463,6 +3463,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi } assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts?", max_attempts); + assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts (size %zu, alignment %zu, file descriptor %d)", max_attempts, size, alignment, file_desc); return aligned_base; } From c01f53ac2dab1d4d2cd1e4d45a67f9373d4a9c7e Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Fri, 9 Aug 2024 07:17:59 +0000 Subject: [PATCH 20/84] 8337876: [IR Framework] Add support for IR tests with @Stable Reviewed-by: shade, kvn --- .../jtreg/compiler/lib/ir_framework/README.md | 11 ++- .../lib/ir_framework/TestFramework.java | 13 +++- .../ir_framework/driver/TestVMProcess.java | 15 ++-- .../tests/TestPhaseIRMatching.java | 2 +- .../tests/TestPrivilegedMode.java | 69 +++++++++++++++++++ 5 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/README.md b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md index 3f6e0d4163f..55d9fcbaece 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/README.md +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md @@ -157,7 +157,16 @@ The framework allows the use of additional compiler control annotations for help - [@ForceCompile](./ForceCompile.java) - [@ForceCompileClassInitializer](./ForceCompileClassInitializer.java) -### 2.5 Framework Debug and Stress Flags +### 2.5 IR Tests with Privileged Classes +To run tests in a privileged mode (e.g. when using `@Stable`, `@Contended`, `@ReservedStackAccess` etc.), one need to add the test classes to the boot classpath. This can easily be achieved by calling `TestFramework.addTestClassesToBootClassPath()` on the test framework object: +``` +TestFramework testFramework = new TestFramework(); +testFramework + .addTestClassesToBootClassPath() + .start(); +``` + +### 2.6 Framework Debug and Stress Flags The framework provides various stress and debug flags. They should mainly be used as JTreg VM and/or Javaoptions (apart from `VerifyIR`). The following (property) flags are supported: - `-DVerifyIR=false`: Explicitly disable IR verification. This is useful, for example, if some scenarios use VM flags that let `@IR` annotation rules fail and the user does not want to provide separate IR rules or add flag preconditions to the already existing IR rules. diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 67fadbc4eac..d477aa44763 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -172,6 +172,7 @@ public class TestFramework { private Set scenarioIndices; private List flags; private int defaultWarmup = -1; + private boolean testClassesOnBootClassPath; /* * Public interface methods @@ -323,6 +324,15 @@ public TestFramework addScenarios(Scenario... scenarios) { return this; } + /** + * Add test classes to boot classpath. This adds all classes found on path {@link jdk.test.lib.Utils#TEST_CLASSES} + * to the boot classpath with "-Xbootclasspath/a". This is useful when trying to run tests in a privileged mode. + */ + public TestFramework addTestClassesToBootClassPath() { + this.testClassesOnBootClassPath = true; + return this; + } + /** * Start the testing of the implicitly (by {@link #TestFramework()}) or explicitly (by {@link #TestFramework(Class)}) * set test class. @@ -744,7 +754,8 @@ private boolean onlyWhitelistedJTregVMAndJavaOptsFlags() { } private void runTestVM(List additionalFlags) { - TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup); + TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup, + testClassesOnBootClassPath); if (shouldVerifyIR) { try { TestClassParser testClassParser = new TestClassParser(testClass); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java index 04f8096d969..8c168b73260 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java @@ -34,6 +34,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import java.io.File; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -63,11 +64,12 @@ public class TestVMProcess { private OutputAnalyzer oa; private String irEncoding; - public TestVMProcess(List additionalFlags, Class testClass, Set> helperClasses, int defaultWarmup) { + public TestVMProcess(List additionalFlags, Class testClass, Set> helperClasses, int defaultWarmup, + boolean testClassesOnBootClassPath) { this.cmds = new ArrayList<>(); TestFrameworkSocket socket = new TestFrameworkSocket(); try (socket) { - prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup); + prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup, testClassesOnBootClassPath); start(); } processSocketOutput(socket); @@ -91,11 +93,16 @@ public static String getLastTestVMOutput() { } private void prepareTestVMFlags(List additionalFlags, TestFrameworkSocket socket, Class testClass, - Set> helperClasses, int defaultWarmup) { + Set> helperClasses, int defaultWarmup, boolean testClassesOnBootClassPath) { // Set java.library.path so JNI tests which rely on jtreg nativepath setting work cmds.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH); // Need White Box access in test VM. - cmds.add("-Xbootclasspath/a:."); + String bootClassPath = "-Xbootclasspath/a:."; + if (testClassesOnBootClassPath) { + // Add test classes themselves to boot classpath to make them privileged. + bootClassPath += File.pathSeparator + Utils.TEST_CLASSES; + } + cmds.add(bootClassPath); cmds.add("-XX:+UnlockDiagnosticVMOptions"); cmds.add("-XX:+WhiteBoxAPI"); // Ignore CompileCommand flags which have an impact on the profiling information. diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java index 9a39fb5310f..f0056ebc79d 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java @@ -66,7 +66,7 @@ private static void run(Class testClass) { List noAdditionalFlags = new ArrayList<>(); FlagVMProcess flagVMProcess = new FlagVMProcess(testClass, noAdditionalFlags); List testVMFlags = flagVMProcess.getTestVMFlags(); - TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1); + TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1, false); TestClassParser testClassParser = new TestClassParser(testClass); Matchable testClassMatchable = testClassParser.parse(testVMProcess.getHotspotPidFileName(), testVMProcess.getIrEncoding()); diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java new file mode 100644 index 00000000000..347b2eb39fb --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package ir_framework.tests; + +import compiler.lib.ir_framework.*; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; + +import jdk.internal.vm.annotation.Stable; +import jdk.test.lib.Asserts; + +/* + * @test + * @requires vm.flagless + * @summary Test that IR framework successfully adds test class to boot classpath in order to run in privileged mode. + * @modules java.base/jdk.internal.vm.annotation + * @library /test/lib / + * @run driver ir_framework.tests.TestPrivilegedMode + */ + +public class TestPrivilegedMode { + static @Stable int iFld; // Treated as constant after first being set. + + public static void main(String[] args) { + try { + TestFramework.run(); + Asserts.fail("should not reach"); + } catch (IRViolationException e) { + // Without adding test class to boot classpath, we fail to replace the field load by a constant. + Asserts.assertTrue(e.getExceptionInfo().contains("Matched forbidden node")); + Asserts.assertTrue(e.getExceptionInfo().contains("LoadI")); + } + + // When adding the test class to the boot classpath, we can replace the field load by a constant. + new TestFramework().addTestClassesToBootClassPath().start(); + } + + @Test + @Arguments(setup = "setup") + @IR(failOn = IRNode.LOAD_I) + public int test() { + return iFld; + } + + @Setup + public void setup() { + iFld = 34; + } +} From 82d5768c1bdccfaf97a41f32a8bfcfd03a0fb378 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Fri, 9 Aug 2024 07:20:01 +0000 Subject: [PATCH 21/84] 8337840: Remove redundant null check in ObjectOutputStream.writeProxyDesc Reviewed-by: rriggs --- src/java.base/share/classes/java/io/ObjectOutputStream.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 2dcf174cf53..3650b101353 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1272,7 +1272,7 @@ private void writeProxyDesc(ObjectStreamClass desc, boolean unshared) } bout.setBlockDataMode(true); - if (cl != null && isCustomSubclass()) { + if (isCustomSubclass()) { ReflectUtil.checkPackageAccess(cl); } annotateProxyClass(cl); From f74109bd178c92a9dff1ca6fce03b25f51a0384f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Fri, 9 Aug 2024 07:29:56 +0000 Subject: [PATCH 22/84] 8337939: ZGC: Make assertions and checks less convoluted and explicit Reviewed-by: stefank, ayang, eosterlund --- src/hotspot/share/gc/z/zAddress.cpp | 6 ++-- src/hotspot/share/gc/z/zAddress.inline.hpp | 30 +++++++++++++++---- src/hotspot/share/gc/z/zBarrier.inline.hpp | 6 ++-- src/hotspot/share/gc/z/zBarrierSet.inline.hpp | 4 +-- src/hotspot/share/gc/z/zHeapIterator.cpp | 2 +- src/hotspot/share/gc/z/zMark.cpp | 4 +-- src/hotspot/share/gc/z/zMark.inline.hpp | 4 +-- src/hotspot/share/gc/z/zPage.inline.hpp | 2 +- .../share/gc/z/zReferenceProcessor.cpp | 4 +-- src/hotspot/share/gc/z/zVerify.cpp | 24 +++++++++------ 10 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/hotspot/share/gc/z/zAddress.cpp b/src/hotspot/share/gc/z/zAddress.cpp index d1c199fad07..1cd33e44a05 100644 --- a/src/hotspot/share/gc/z/zAddress.cpp +++ b/src/hotspot/share/gc/z/zAddress.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,9 +93,7 @@ static void initialize_check_oop_function() { #ifdef CHECK_UNHANDLED_OOPS if (ZVerifyOops) { // Enable extra verification of usages of oops in oopsHierarchy.hpp - check_oop_function = [](oopDesc* obj) { - (void)to_zaddress(obj); - }; + check_oop_function = &check_is_valid_zaddress; } #endif } diff --git a/src/hotspot/share/gc/z/zAddress.inline.hpp b/src/hotspot/share/gc/z/zAddress.inline.hpp index 4adbf50bc86..bbc92a7e2aa 100644 --- a/src/hotspot/share/gc/z/zAddress.inline.hpp +++ b/src/hotspot/share/gc/z/zAddress.inline.hpp @@ -333,10 +333,22 @@ inline void dereferenceable_test(zaddress addr) { } #endif -inline zaddress to_zaddress(uintptr_t value) { - const zaddress addr = zaddress(value); +inline void check_is_valid_zaddress(zaddress addr) { assert_is_valid(addr); DEBUG_ONLY(dereferenceable_test(addr)); +} + +inline void check_is_valid_zaddress(uintptr_t value) { + check_is_valid_zaddress(zaddress(value)); +} + +inline void check_is_valid_zaddress(oopDesc* o) { + check_is_valid_zaddress(uintptr_t(o)); +} + +inline zaddress to_zaddress(uintptr_t value) { + const zaddress addr = zaddress(value); + check_is_valid_zaddress(addr); return addr; } @@ -344,7 +356,7 @@ inline zaddress to_zaddress(oopDesc* o) { return to_zaddress(uintptr_t(o)); } -inline oop to_oop(zaddress addr) { +inline void assert_is_oop_or_null(zaddress addr) { const oop obj = cast_to_oop(addr); assert(!ZVerifyOops || oopDesc::is_oop_or_null(obj), "Broken oop: " PTR_FORMAT " [" PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT "]", p2i(obj), @@ -352,7 +364,16 @@ inline oop to_oop(zaddress addr) { *(uintptr_t*)(untype(addr) + 0x08), *(uintptr_t*)(untype(addr) + 0x10), *(uintptr_t*)(untype(addr) + 0x18)); - return obj; +} + +inline void assert_is_oop(zaddress addr) { + assert(!is_null(addr), "Should not be null"); + assert_is_oop_or_null(addr); +} + +inline oop to_oop(zaddress addr) { + assert_is_oop_or_null(addr); + return cast_to_oop(addr); } inline zaddress operator+(zaddress addr, size_t size) { @@ -378,7 +399,6 @@ inline void assert_is_valid(zaddress_unsafe addr) { DEBUG_ONLY(is_valid(addr, true /* assert_on_failure */);) } - inline uintptr_t untype(zaddress_unsafe addr) { return static_cast(addr); } diff --git a/src/hotspot/share/gc/z/zBarrier.inline.hpp b/src/hotspot/share/gc/z/zBarrier.inline.hpp index b3191e9ae3f..a3eb7a9ca67 100644 --- a/src/hotspot/share/gc/z/zBarrier.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -745,7 +745,7 @@ inline void ZBarrier::mark_and_remember(volatile zpointer* p, zaddress addr) { template inline void ZBarrier::mark(zaddress addr) { - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop"); + assert_is_oop(addr); if (ZHeap::heap()->is_old(addr)) { ZGeneration::old()->mark_object_if_active(addr); @@ -757,7 +757,7 @@ inline void ZBarrier::mark(zaddress addr) { template inline void ZBarrier::mark_young(zaddress addr) { assert(ZGeneration::young()->is_phase_mark(), "Should only be called during marking"); - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop"); + assert_is_oop(addr); assert(ZHeap::heap()->is_young(addr), "Must be young"); ZGeneration::young()->mark_object(addr); diff --git a/src/hotspot/share/gc/z/zBarrierSet.inline.hpp b/src/hotspot/share/gc/z/zBarrierSet.inline.hpp index d53b69345dd..174cdfd9e90 100644 --- a/src/hotspot/share/gc/z/zBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrierSet.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -430,7 +430,7 @@ class ZLoadBarrierOopClosure : public BasicOopIterateClosure { template inline void ZBarrierSet::AccessBarrier::clone_in_heap(oop src, oop dst, size_t size) { - assert_is_valid(to_zaddress(src)); + check_is_valid_zaddress(src); if (dst->is_objArray()) { // Cloning an object array is similar to performing array copy. diff --git a/src/hotspot/share/gc/z/zHeapIterator.cpp b/src/hotspot/share/gc/z/zHeapIterator.cpp index 50fc921131f..e149a976add 100644 --- a/src/hotspot/share/gc/z/zHeapIterator.cpp +++ b/src/hotspot/share/gc/z/zHeapIterator.cpp @@ -146,7 +146,7 @@ class ZHeapIteratorUncoloredRootOopClosure : public OopClosure { oop load_oop(oop* p) { const oop o = Atomic::load(p); - assert_is_valid(to_zaddress(o)); + check_is_valid_zaddress(o); return RawAccess<>::oop_load(p); } diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index eb342495f57..d33b86c83e5 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -365,7 +365,7 @@ void ZMark::follow_array_object(objArrayOop obj, bool finalizable) { } // Should be convertible to colorless oop - assert_is_valid(to_zaddress(obj)); + check_is_valid_zaddress(obj); zpointer* const addr = (zpointer*)obj->base(); const size_t length = (size_t)obj->length(); diff --git a/src/hotspot/share/gc/z/zMark.inline.hpp b/src/hotspot/share/gc/z/zMark.inline.hpp index b5302593610..9edc57a6000 100644 --- a/src/hotspot/share/gc/z/zMark.inline.hpp +++ b/src/hotspot/share/gc/z/zMark.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ template inline void ZMark::mark_object(zaddress addr) { - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr)), "Should be oop"); + assert_is_oop(addr); ZPage* const page = _page_table->get(addr); if (page->is_allocating()) { diff --git a/src/hotspot/share/gc/z/zPage.inline.hpp b/src/hotspot/share/gc/z/zPage.inline.hpp index fcf69c685f7..d8ecad57190 100644 --- a/src/hotspot/share/gc/z/zPage.inline.hpp +++ b/src/hotspot/share/gc/z/zPage.inline.hpp @@ -311,7 +311,7 @@ inline bool ZPage::mark_object(zaddress addr, bool finalizable, bool& inc_live) assert(is_in(addr), "Invalid address"); // Verify oop - (void)to_oop(addr); + assert_is_oop(addr); // Set mark bit const BitMap::idx_t index = bit_index(addr); diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.cpp b/src/hotspot/share/gc/z/zReferenceProcessor.cpp index df8cb2b0e95..1252de2ac27 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -143,7 +143,7 @@ bool ZReferenceProcessor::is_inactive(zaddress reference, oop referent, Referenc return !is_null(reference_next(reference)); } else { // Verification - (void)to_zaddress(referent); + check_is_valid_zaddress(referent); // A non-FinalReference is inactive if the referent is null. The referent can only // be null if the application called Reference.enqueue() or Reference.clear(). diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index d47886ec7c2..b735965e9d4 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -111,6 +111,16 @@ static bool z_is_null_relaxed(zpointer o) { return (untype(o) & ~color_mask) == 0; } +static void z_verify_oop_object(zaddress addr, zpointer o, void* p) { + const oop obj = cast_to_oop(addr); + guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(o, p)); +} + +static void z_verify_root_oop_object(zaddress addr, void* p) { + const oop obj = cast_to_oop(addr); + guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(addr, p)); +} + static void z_verify_old_oop(zpointer* p) { const zpointer o = *p; assert(o != zpointer::null, "Old should not contain raw null"); @@ -121,7 +131,7 @@ static void z_verify_old_oop(zpointer* p) { // safepoint after reference processing, where we hold the driver lock and // know there is no concurrent remembered set processing in the young generation. const zaddress addr = ZPointer::uncolor(o); - guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p)); + z_verify_oop_object(addr, o, p); } else { const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); // Old to young pointers might not be mark good if the young @@ -143,15 +153,11 @@ static void z_verify_young_oop(zpointer* p) { guarantee(ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p)); if (ZPointer::is_load_good(o)) { - guarantee(oopDesc::is_oop(to_oop(ZPointer::uncolor(o))), BAD_OOP_ARG(o, p)); + z_verify_oop_object(ZPointer::uncolor(o), o, p); } } } -static void z_verify_root_oop_object(zaddress o, void* p) { - guarantee(oopDesc::is_oop(to_oop(o)), BAD_OOP_ARG(o, p)); -} - static void z_verify_uncolored_root_oop(zaddress* p) { assert(!ZHeap::heap()->is_in((uintptr_t)p), "Roots shouldn't be in heap"); const zaddress o = *p; @@ -168,7 +174,7 @@ static void z_verify_possibly_weak_oop(zpointer* p) { const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); guarantee(ZHeap::heap()->is_old(addr) || ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p)); guarantee(ZHeap::heap()->is_young(addr) || ZHeap::heap()->is_object_live(addr), BAD_OOP_ARG(o, p)); - guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p)); + z_verify_oop_object(addr, o, p); // Verify no missing remset entries. We are holding the driver lock here and that // allows us to more precisely verify the remembered set, as there is no concurrent @@ -211,14 +217,14 @@ class ZVerifyColoredRootClosure : public OopClosure { // Minor collections could have relocated the object; // use load barrier to find correct object. const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); - z_verify_root_oop_object(addr, p); + z_verify_oop_object(addr, o, p); } else { // Don't know the state of the oop if (is_valid(o)) { // it looks like a valid colored oop; // use load barrier to find correct object. const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); - z_verify_root_oop_object(addr, p); + z_verify_oop_object(addr, o, p); } } } From 53fce38a3ff8700fef640fffc066efc21ff9c25f Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 9 Aug 2024 07:53:15 +0000 Subject: [PATCH 23/84] 8338062: JFR: Remove TestStartDuration.java and TestStartName.java from ProblemList.txt Reviewed-by: mgronlun --- test/jdk/ProblemList.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8aedbc77931..293d9d108d3 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -745,8 +745,6 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 -jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 -jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all ############################################################################ From 6ebd5d74d57b334e7cf0b1282d7bb469a56fb3d6 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 9 Aug 2024 08:23:44 +0000 Subject: [PATCH 24/84] 8338036: Serial: Remove Generation::update_counters Reviewed-by: kbarrett --- src/hotspot/share/gc/serial/generation.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/serial/generation.hpp b/src/hotspot/share/gc/serial/generation.hpp index beb29928f48..c6a9f94a870 100644 --- a/src/hotspot/share/gc/serial/generation.hpp +++ b/src/hotspot/share/gc/serial/generation.hpp @@ -114,8 +114,7 @@ class Generation: public CHeapObj { public: // Performance Counter support - virtual void update_counters() = 0; - virtual CollectorCounters* counters() { return _gc_counters; } + CollectorCounters* counters() { return _gc_counters; } GCMemoryManager* gc_manager() const { assert(_gc_manager != nullptr, "not initialized yet"); From c37e8638c98cb4516569304e9a0ab477affb0641 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Fri, 9 Aug 2024 09:12:41 +0000 Subject: [PATCH 25/84] 8314125: RISC-V: implement Base64 intrinsic - encoding Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 13 + src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 223 ++++++++++++++++++ src/hotspot/cpu/riscv/vm_version_riscv.cpp | 5 + 3 files changed, 241 insertions(+) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index e4280ab34e1..79279be7acc 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1828,6 +1828,19 @@ enum Nf { #undef INSN +#define INSN(NAME, op, width, umop, mop, mew, nf) \ + void NAME(VectorRegister Vd_or_Vs3, Register Rs1, VectorMask vm = unmasked) { \ + patch_VLdSt(op, Vd_or_Vs3, width, Rs1, umop, vm, mop, mew, nf); \ + } + + // Vector Unit-Stride Segment Load Instructions + INSN(vlseg3e8_v, 0b0000111, 0b000, 0b00000, 0b00, 0b0, g3); + + // Vector Unit-Stride Segment Store Instructions + INSN(vsseg4e8_v, 0b0100111, 0b000, 0b00000, 0b00, 0b0, g4); + +#undef INSN + #define INSN(NAME, op, width, mop, mew) \ void NAME(VectorRegister Vd, Register Rs1, VectorRegister Vs2, VectorMask vm = unmasked, Nf nf = g1) { \ patch_VLdSt(op, Vd, width, Rs1, Vs2->raw_encoding(), vm, mop, mew, nf); \ diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 198835d733f..6a2c6c7d6c9 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -5103,6 +5103,225 @@ class StubGenerator: public StubCodeGenerator { return (address) start; } + /** + * vector registers: + * input VectorRegister's: intputV1-V3, for m2 they could be v2, v4, v6, for m1 they could be v1, v2, v3 + * index VectorRegister's: idxV1-V4, for m2 they could be v8, v10, v12, v14, for m1 they could be v4, v5, v6, v7 + * output VectorRegister's: outputV1-V4, for m2 they could be v16, v18, v20, v22, for m1 they could be v8, v9, v10, v11 + * + * NOTE: each field will occupy a vector register group + */ + void base64_vector_encode_round(Register src, Register dst, Register codec, + Register size, Register stepSrc, Register stepDst, + VectorRegister inputV1, VectorRegister inputV2, VectorRegister inputV3, + VectorRegister idxV1, VectorRegister idxV2, VectorRegister idxV3, VectorRegister idxV4, + VectorRegister outputV1, VectorRegister outputV2, VectorRegister outputV3, VectorRegister outputV4, + Assembler::LMUL lmul) { + // set vector register type/len + __ vsetvli(x0, size, Assembler::e8, lmul); + + // segmented load src into v registers: mem(src) => vr(3) + __ vlseg3e8_v(inputV1, src); + + // src = src + register_group_len_bytes * 3 + __ add(src, src, stepSrc); + + // encoding + // 1. compute index into lookup table: vr(3) => vr(4) + __ vsrl_vi(idxV1, inputV1, 2); + + __ vsrl_vi(idxV2, inputV2, 2); + __ vsll_vi(inputV1, inputV1, 6); + __ vor_vv(idxV2, idxV2, inputV1); + __ vsrl_vi(idxV2, idxV2, 2); + + __ vsrl_vi(idxV3, inputV3, 4); + __ vsll_vi(inputV2, inputV2, 4); + __ vor_vv(idxV3, inputV2, idxV3); + __ vsrl_vi(idxV3, idxV3, 2); + + __ vsll_vi(idxV4, inputV3, 2); + __ vsrl_vi(idxV4, idxV4, 2); + + // 2. indexed load: vr(4) => vr(4) + __ vluxei8_v(outputV1, codec, idxV1); + __ vluxei8_v(outputV2, codec, idxV2); + __ vluxei8_v(outputV3, codec, idxV3); + __ vluxei8_v(outputV4, codec, idxV4); + + // segmented store encoded data in v registers back to dst: vr(4) => mem(dst) + __ vsseg4e8_v(outputV1, dst); + + // dst = dst + register_group_len_bytes * 4 + __ add(dst, dst, stepDst); + } + + /** + * void j.u.Base64.Encoder.encodeBlock(byte[] src, int sp, int sl, byte[] dst, int dp, boolean isURL) + * + * Input arguments: + * c_rarg0 - src, source array + * c_rarg1 - sp, src start offset + * c_rarg2 - sl, src end offset + * c_rarg3 - dst, dest array + * c_rarg4 - dp, dst start offset + * c_rarg5 - isURL, Base64 or URL character set + */ + address generate_base64_encodeBlock() { + alignas(64) static const char toBase64[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + alignas(64) static const char toBase64URL[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' + }; + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "encodeBlock"); + address start = __ pc(); + __ enter(); + + Register src = c_rarg0; + Register soff = c_rarg1; + Register send = c_rarg2; + Register dst = c_rarg3; + Register doff = c_rarg4; + Register isURL = c_rarg5; + + Register codec = c_rarg6; + Register length = c_rarg7; // total length of src data in bytes + + Label ProcessData, Exit; + + // length should be multiple of 3 + __ sub(length, send, soff); + // real src/dst to process data + __ add(src, src, soff); + __ add(dst, dst, doff); + + // load the codec base address + __ la(codec, ExternalAddress((address) toBase64)); + __ beqz(isURL, ProcessData); + __ la(codec, ExternalAddress((address) toBase64URL)); + __ BIND(ProcessData); + + // vector version + if (UseRVV) { + Label ProcessM2, ProcessM1, ProcessScalar; + + Register size = soff; + Register stepSrcM1 = send; + Register stepSrcM2 = doff; + Register stepDst = isURL; + + __ mv(size, MaxVectorSize * 2); + __ mv(stepSrcM1, MaxVectorSize * 3); + __ slli(stepSrcM2, stepSrcM1, 1); + __ mv(stepDst, MaxVectorSize * 2 * 4); + + __ blt(length, stepSrcM2, ProcessM1); + + __ BIND(ProcessM2); + base64_vector_encode_round(src, dst, codec, + size, stepSrcM2, stepDst, + v2, v4, v6, // inputs + v8, v10, v12, v14, // indexes + v16, v18, v20, v22, // outputs + Assembler::m2); + + __ sub(length, length, stepSrcM2); + __ bge(length, stepSrcM2, ProcessM2); + + __ BIND(ProcessM1); + __ blt(length, stepSrcM1, ProcessScalar); + + __ srli(size, size, 1); + __ srli(stepDst, stepDst, 1); + base64_vector_encode_round(src, dst, codec, + size, stepSrcM1, stepDst, + v1, v2, v3, // inputs + v4, v5, v6, v7, // indexes + v8, v9, v10, v11, // outputs + Assembler::m1); + __ sub(length, length, stepSrcM1); + + __ BIND(ProcessScalar); + } + + // scalar version + { + Register byte1 = soff, byte0 = send, byte2 = doff; + Register combined24Bits = isURL; + + __ beqz(length, Exit); + + Label ScalarLoop; + __ BIND(ScalarLoop); + { + // plain: [byte0[7:0] : byte1[7:0] : byte2[7:0]] => + // encoded: [byte0[7:2] : byte0[1:0]+byte1[7:4] : byte1[3:0]+byte2[7:6] : byte2[5:0]] + + // load 3 bytes src data + __ lbu(byte0, Address(src, 0)); + __ lbu(byte1, Address(src, 1)); + __ lbu(byte2, Address(src, 2)); + __ addi(src, src, 3); + + // construct 24 bits from 3 bytes + __ slliw(byte0, byte0, 16); + __ slliw(byte1, byte1, 8); + __ orr(combined24Bits, byte0, byte1); + __ orr(combined24Bits, combined24Bits, byte2); + + // get codec index and encode(ie. load from codec by index) + __ slliw(byte0, combined24Bits, 8); + __ srliw(byte0, byte0, 26); + __ add(byte0, codec, byte0); + __ lbu(byte0, byte0); + + __ slliw(byte1, combined24Bits, 14); + __ srliw(byte1, byte1, 26); + __ add(byte1, codec, byte1); + __ lbu(byte1, byte1); + + __ slliw(byte2, combined24Bits, 20); + __ srliw(byte2, byte2, 26); + __ add(byte2, codec, byte2); + __ lbu(byte2, byte2); + + __ andi(combined24Bits, combined24Bits, 0x3f); + __ add(combined24Bits, codec, combined24Bits); + __ lbu(combined24Bits, combined24Bits); + + // store 4 bytes encoded data + __ sb(byte0, Address(dst, 0)); + __ sb(byte1, Address(dst, 1)); + __ sb(byte2, Address(dst, 2)); + __ sb(combined24Bits, Address(dst, 3)); + + __ sub(length, length, 3); + __ addi(dst, dst, 4); + // loop back + __ bnez(length, ScalarLoop); + } + } + + __ BIND(Exit); + + __ leave(); + __ ret(); + + return (address) start; + } + void adler32_process_bytes(Register buff, Register s1, Register s2, VectorRegister vtable, VectorRegister vzero, VectorRegister vbytes, VectorRegister vs1acc, VectorRegister vs2acc, Register temp0, Register temp1, Register temp2, Register temp3, @@ -5996,6 +6215,10 @@ static const int64_t right_3_bits = right_n_bits(3); StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); } + if (UseBASE64Intrinsics) { + StubRoutines::_base64_encodeBlock = generate_base64_encodeBlock(); + } + if (UseAdler32Intrinsics) { StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32(); } diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index ac2d6cde1a2..e9c6226f446 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -265,6 +265,11 @@ void VM_Version::c2_initialize() { // as there are extra checks inside it which could disable UseRVV // in some situations. + // Base64 + if (FLAG_IS_DEFAULT(UseBASE64Intrinsics)) { + FLAG_SET_DEFAULT(UseBASE64Intrinsics, true); + } + if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) { FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true); } From 140716078694a338e2c2f837841761262cee5542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Fri, 9 Aug 2024 09:24:50 +0000 Subject: [PATCH 26/84] 8313931: Javadoc: links to type parameters actually generate links to classes Reviewed-by: jjg --- .../doclets/formats/html/ClassWriter.java | 50 +++++-- .../doclets/formats/html/HtmlIds.java | 16 +++ .../doclets/formats/html/HtmlLinkFactory.java | 13 +- .../formats/html/resources/script.js.template | 18 ++- .../formats/html/resources/stylesheet.css | 22 +++- .../formats/html/taglets/LinkTaglet.java | 24 +++- .../formats/html/taglets/ParamTaglet.java | 6 +- .../doclets/toolkit/util/CommentHelper.java | 6 + .../TestDeprecatedDocs.java | 8 +- .../TestDirectedInheritance.java | 6 +- .../doclet/testErasure/TestErasure.java | 8 +- .../TestGenericMethodLinkTaglet.java | 6 +- .../jdk/javadoc/doclet/testHref/TestHref.java | 5 +- .../doclet/testInterface/TestInterface.java | 36 ++--- .../TestLinkTagletTypeParam.java | 124 ++++++++++++++++++ .../TestMemberInheritance.java | 4 +- .../doclet/testModules/TestModules.java | 2 +- .../TestNewLanguageFeatures.java | 22 ++-- .../testParamTaglet/TestParamTaglet.java | 6 +- .../doclet/testProperty/TestProperty.java | 4 +- .../testRecordTypes/TestRecordTypes.java | 2 +- .../TestSerializedForm.java | 5 +- .../javadoc/doclet/testThrows/TestThrows.java | 4 +- .../testTypeParams/TestTypeParameters.java | 20 ++- .../testTypeParams/pkg/CtorTypeParam.java | 6 + .../doclet/testUnicode/TestUnicode.java | 4 +- 26 files changed, 336 insertions(+), 91 deletions(-) create mode 100644 test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java index a1fd27fefdd..8218e5128be 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java @@ -37,6 +37,7 @@ import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.SimpleElementVisitor8; @@ -155,7 +156,7 @@ protected void buildClassTree(Content classContent) { * @param target the content to which the documentation will be added */ protected void buildClassInfo(Content target) { - Content c = HtmlTree.DIV(HtmlStyles.horizontalScroll); + var c = new ContentBuilder(); buildParamInfo(c); buildSuperInterfacesInfo(c); buildImplementedInterfacesInfo(c); @@ -164,11 +165,13 @@ protected void buildClassInfo(Content target) { buildInterfaceUsageInfo(c); buildNestedClassInfo(c); buildFunctionalInterfaceInfo(c); - buildClassSignature(c); - buildDeprecationInfo(c); - buildClassDescription(c); - buildClassTagInfo(c); - + c.add(new HtmlTree(HtmlTag.HR)); + var div = HtmlTree.DIV(HtmlStyles.horizontalScroll); + buildClassSignature(div); + buildDeprecationInfo(div); + buildClassDescription(div); + buildClassTagInfo(div); + c.add(div); target.add(getClassInfo(c)); } @@ -432,12 +435,9 @@ private void setRecordDocumentation(TypeElement elem) { protected Content getHeader(String header) { HtmlTree body = getBody(getWindowTitle(utils.getSimpleName(typeElement))); var div = HtmlTree.DIV(HtmlStyles.header); - HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration, - HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_AND_BOUNDS, typeElement) - .linkToSelf(false); // Let's not link to ourselves in the header var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyles.title, Text.of(header)); - heading.add(getTypeParameterLinks(linkInfo)); + heading.add(getTypeParameters()); div.add(heading); bodyContents.setHeader(getHeader(PageMode.CLASS, typeElement)) .addMainContent(MarkerComments.START_OF_CLASS_DATA) @@ -445,6 +445,35 @@ protected Content getHeader(String header) { return body; } + // Renders type parameters for the class heading, creating id attributes + // if @param block tags are missing in doc comment. + private Content getTypeParameters() { + var content = new ContentBuilder(); + var typeParams = typeElement.getTypeParameters(); + if (!typeParams.isEmpty()) { + // Generate id attributes if @param tags are missing for type parameters. + // Note that this does not handle the case where some but not all @param tags are missing. + var needsId = !utils.hasBlockTag(typeElement, DocTree.Kind.PARAM); + var linkInfo = new HtmlLinkInfo(configuration, + HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_AND_BOUNDS, typeElement) + .linkToSelf(false); // Let's not link to ourselves in the header + content.add("<"); + var first = true; + for (TypeParameterElement t : typeParams) { + if (!first) { + content.add(",").add(new HtmlTree(HtmlTag.WBR)); + } + var typeParamLink = getLink(linkInfo.forType(t.asType())); + content.add(needsId + ? HtmlTree.SPAN_ID(htmlIds.forTypeParam(t.getSimpleName().toString(), typeElement), typeParamLink) + : typeParamLink); + first = false; + } + content.add(">"); + } + return content; + } + protected Content getClassContentHeader() { return getContentHeader(); } @@ -473,7 +502,6 @@ public TypeElement getCurrentPageElement() { } protected void addClassSignature(Content classInfo) { - classInfo.add(new HtmlTree(HtmlTag.HR)); classInfo.add(new Signatures.TypeSignature(typeElement, this) .toContent()); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java index 1b9896fafa0..8b48c7a6f22 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java @@ -462,6 +462,22 @@ public static HtmlId forText(String text, Map counts) { return HtmlId.of(count == 0 ? base : base + "-" + count); } + /** + * Returns an id for text documenting a type parameter of a class or method. + * + * @param paramName the name of the type parameter + * @param owner the enclosing element + * + * @return the id + */ + public HtmlId forTypeParam(String paramName, Element owner) { + if (utils.isExecutableElement(owner)) { + return HtmlId.of(forMember((ExecutableElement) owner).getFirst().name() + + "-type-param-" + paramName); + } + return HtmlId.of("type-param-" + paramName); + } + /** * Returns an id for one of the kinds of section in the pages for item group summaries. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java index 22af1e4a024..8e0c010dd1a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java @@ -162,9 +162,11 @@ public Content visitTypeVariable(TypeVariable type, HtmlLinkInfo linkInfo) { Element owner = typevariable.asElement().getEnclosingElement(); if (linkInfo.linkTypeParameters() && utils.isTypeElement(owner)) { linkInfo.setTypeElement((TypeElement) owner); - Content label = newContent(); - label.add(utils.getTypeName(type, false)); - linkInfo.label(label).skipPreview(true); + if (linkInfo.getLabel() == null || linkInfo.getLabel().isEmpty()) { + Content label = newContent(); + label.add(utils.getTypeName(type, false)); + linkInfo.label(label).skipPreview(true); + } link.add(getClassLink(linkInfo)); } else { // No need to link method type parameters. @@ -242,6 +244,11 @@ protected Content getClassLink(HtmlLinkInfo linkInfo) { boolean isTypeLink = linkInfo.getType() != null && utils.isTypeVariable(utils.getComponentType(linkInfo.getType())); title = getClassToolTip(typeElement, isTypeLink); + if (isTypeLink) { + linkInfo.fragment(m_writer.configuration.htmlIds.forTypeParam( + utils.getTypeName(utils.getComponentType(linkInfo.getType()), false), + typeElement).name()); + } } Content label = linkInfo.getClassLinkLabel(configuration); if (linkInfo.getContext() == HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_IN_LABEL) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template index ef09e6df90f..71ef8476708 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template @@ -232,6 +232,20 @@ document.addEventListener("readystatechange", (e) => { }); document.addEventListener("DOMContentLoaded", function(e) { setTopMargin(); + // Reset animation for type parameter target highlight + document.querySelectorAll("a").forEach((link) => { + link.addEventListener("click", (e) => { + const href = e.currentTarget.getAttribute("href"); + if (href && href.startsWith("#") && href.indexOf("type-param-") > -1) { + const target = document.getElementById(decodeURI(href.substring(1))); + if (target) { + target.style.animation = "none"; + void target.offsetHeight; + target.style.removeProperty("animation"); + } + } + }) + }); // Make sure current element is visible in breadcrumb navigation on small displays const subnav = document.querySelector("ol.sub-nav-list"); if (subnav && subnav.lastElementChild) { @@ -286,7 +300,7 @@ document.addEventListener("DOMContentLoaded", function(e) { }); var expanded = false; var windowWidth; - function collapse() { + function collapse(e) { if (expanded) { mainnav.removeAttribute("style"); if (toc) { @@ -336,7 +350,7 @@ document.addEventListener("DOMContentLoaded", function(e) { document.querySelectorAll("h1, h2, h3, h4, h5, h6") .forEach((hdr, idx) => { // Create anchor links for headers with an associated id attribute - var id = hdr.getAttribute("id") || hdr.parentElement.getAttribute("id") + var id = hdr.parentElement.getAttribute("id") || hdr.getAttribute("id") || (hdr.querySelector("a") && hdr.querySelector("a").getAttribute("id")); if (id) { var template = document.createElement('template'); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index 4e37588f6cd..1130f14dc35 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -63,7 +63,7 @@ --search-input-text-color: #000000; --search-input-placeholder-color: #909090; /* Highlight color for active search tag target */ - --search-tag-highlight-color: #ffff00; + --search-tag-highlight-color: #ffff66; /* Adjustments for icon and active background colors of copy-to-clipboard buttons */ --copy-icon-brightness: 100%; --copy-button-background-color-active: rgba(168, 168, 176, 0.3); @@ -307,7 +307,7 @@ ol.sub-nav-list a.current-selection { */ .title { color:var(--title-color); - margin:10px 0; + margin:10px 0 12px 0; } .sub-title { margin:5px 0 0 0; @@ -988,6 +988,22 @@ input::placeholder { .search-tag-result:target { background-color:var(--search-tag-highlight-color); } +dd > span:target, +h1 > span:target { + animation: 2.4s ease-out highlight; +} +section.class-description dd > span:target, +section.class-description h1 > span:target { + scroll-margin-top: 20em; +} +@keyframes highlight { + from { + background-color: var(--search-tag-highlight-color); + } + 60% { + background-color: var(--search-tag-highlight-color); + } +} details.page-search-details { display: inline-block; } @@ -1040,7 +1056,7 @@ span#page-search-link { z-index: 5; } .inherited-list { - margin: 10px 0 10px 0; + margin: 10px 0; } .horizontal-scroll { overflow: auto hidden; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java index e16acd0315a..b16a1490b63 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -176,7 +176,7 @@ Content linkSeeReferenceOutput(Element holder, return htmlWriter.getPackageLink(refPackage, labelContent, refFragment); } else { // @see is not referencing an included class, module or package. Check for cross-links. - String refModuleName = ch.getReferencedModuleName(refSignature); + String refModuleName = ch.getReferencedModuleName(refSignature); DocLink elementCrossLink = (refPackage != null) ? htmlWriter.getCrossPackageLink(refPackage) : (config.extern.isModule(refModuleName)) ? htmlWriter.getCrossModuleLink(utils.elementUtils.getModuleElement(refModuleName)) @@ -190,12 +190,28 @@ Content linkSeeReferenceOutput(Element holder, if (!config.isDocLintReferenceGroupEnabled()) { reportWarning.accept( "doclet.link.see.reference_not_found", - new Object[] { refSignature}); + new Object[] {refSignature}); } return htmlWriter.invalidTagOutput(resources.getText("doclet.link.see.reference_invalid"), - Optional.of(labelContent.isEmpty() ? text: labelContent)); + Optional.of(labelContent.isEmpty() ? text : labelContent)); } } + } else if (utils.isTypeParameterElement(ref)) { + // This is a type parameter of a generic class, method or constructor + if (labelContent.isEmpty()) { + labelContent = plainOrCode(isPlain, Text.of(utils.getSimpleName(ref))); + } + if (refMem == null) { + return htmlWriter.getLink( + new HtmlLinkInfo(config, HtmlLinkInfo.Kind.LINK_TYPE_PARAMS, ref.asType()) + .label(labelContent)); + } else { + // HtmlLinkFactory does not render type parameters of generic methods as links, so instead of + // teaching it how to do it (making the code even more complex) just create the link directly. + return htmlWriter.getLink(new HtmlLinkInfo(config, HtmlLinkInfo.Kind.PLAIN, refClass) + .fragment(config.htmlIds.forTypeParam(ref.getSimpleName().toString(), refMem).name()) + .label((labelContent))); + } } else if (refFragment == null) { // Must be a class reference since refClass is not null and refFragment is null. if (labelContent.isEmpty() && refTree != null) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java index ed46e6c5c86..8a3c47bbfd4 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -278,7 +278,9 @@ private Content paramTagOutput(Element element, ParamTree paramTag, String param body.add(" - "); List description = ch.getDescription(paramTag); body.add(htmlWriter.commentTagsToContent(element, description, context.within(paramTag))); - return HtmlTree.DD(body); + return HtmlTree.DD(paramTag.isTypeParameter() + ? HtmlTree.SPAN_ID(config.htmlIds.forTypeParam(paramName, element), body) + : body); } private record Documentation(ParamTree paramTree, ExecutableElement method) { } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java index d7a0bd2d0a0..30aa86aea71 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java @@ -188,6 +188,12 @@ public Element getReferencedMember(Element e) { Utils utils = configuration.utils; if (e == null) { return null; + } else if (utils.isTypeParameterElement(e)) { + // Return the enclosing member for type parameters of generic methods or constructors. + Element encl = e.getEnclosingElement(); + if (utils.isExecutableElement(encl)) { + return encl; + } } return (utils.isExecutableElement(e) || utils.isVariableElement(e)) ? e : null; } diff --git a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java index 2bd9da59578..165fadc8e05 100644 --- a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java +++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,7 +102,6 @@ public void test() { checkOutput("pkg/TestAnnotationType.html", true, """ -
@Deprecated(forRemoval=true) @Documented public @interface
@Deprecated(forRemoval=true) public class TestClass extends java.lang.Object
@@ -212,7 +210,6 @@ public void test() { checkOutput("pkg/TestEnum.html", true, """ -
@Deprecated(forRemoval=true) public enum TestEnum extends java.lang.Enum<
@Deprecated(forRemoval=true) public class TestError extends java.lang.Error
@@ -244,7 +240,6 @@ public void test() { checkOutput("pkg/TestException.html", true, """ -
@Deprecated(forRemoval=true) public class TestException extends java.lang.Exception
@@ -255,7 +250,6 @@ public void test() { checkOutput("pkg/TestInterface.html", true, """ -
@Deprecated(forRemoval=true) public class TestInterface extends java.lang.Object
diff --git a/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java b/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java index 89eb68db1df..0f2b398e626 100644 --- a/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,8 +154,8 @@ public interface E1 extends I1, I2 {
I2: main description
""", """
Type Parameters:
-
E - I2: first type parameter
-
F - I2: second type parameter
+
E - I2: first type parameter
+
F - I2: second type parameter
Parameters:
eObj - I2: parameter
Returns:
diff --git a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java index f80074c50e2..ee2ec08b884 100644 --- a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java +++ b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java @@ -199,7 +199,7 @@ class X { }
 
\ Foo\ - (T arg)
+ (T arg)
 
 <T extends X>
\ @@ -227,10 +227,10 @@ class X { } // methods checkOutput("Foo.html", true, """
abstract T
+ method-summary-table-tab3">abstract T
m\ - (T arg)
+ (T arg)
 
Test Feature
"""); } -} \ No newline at end of file +} diff --git a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java index a9a4be1b262..db23064e9ca 100644 --- a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8188248 + * @bug 8188248 8313931 * @summary NullPointerException on generic methods * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -67,7 +67,7 @@ public void test(Path base) throws Exception { checkOutput("pkg/A.html", true, """ - A"""); + param T"""); } void createTestClass(Path srcDir) throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java index f21ad223fb4..b9dff5ff2a8 100644 --- a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java +++ b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,8 @@ public void test() { checkOutput("pkg/C4.html", true, //Header does not link to the page itself. - "Class C4<E extends C4<E>>", + """ + Class C4<E extends C4<E>>""", //Signature does not link to the page itself. """ public abstract class method in interface&\ nbsp;Interface<CE>""", + href="#type-param-CE" title="type parameter in Child">CE>""", //Make sure "Overrides" has substituted type parameters. """
Overrides:
method in class Parent<Parent<CE>
"""); checkOutput("pkg/Parent.html", true, @@ -190,7 +190,7 @@ public void test1() {
Overrides:
method1 in class&\ nbsp;GrandParent<<\ - a href="Child.html" title="type parameter in Child">CE>"""); + a href="#type-param-CE" title="type parameter in Child">CE>"""); } @Test @@ -209,17 +209,17 @@ public void test2() { erface in pkg2">Spliterator Spliterator.\ OfDouble, Spliter\ - ator.OfInt<Integer>, Spliterator.OfPrimitive<T,T_C\ - ONS,T,T_C\ + ONS,T_SPLITR extends Spliterator.OfPrimitive<T,<\ - a href="Spliterator.OfPrimitive.html" title="type parameter in Spliterator.OfPri\ - mitive">T_CONS,T,<\ + a href="Spliterator.OfPrimitive.html#type-param-T_CONS" title="type parameter in Spliterator.OfPri\ + mitive">T_CONS,T_SPLITR>>"""); checkOutput("pkg2/Spliterator.html", true, """ @@ -236,21 +236,21 @@ public void test2() {
static interface 
Spliterator.OfInt<Integer&\ + Spliterator.OfInt.html#type-param-Integer" title="type parameter in Spliterator.OfInt">Integer&\ gt;
 
static interface 
Spliterator.OfPrimitive\ - <T,T,T_CONS,T_SPLITR extends <\ + e.html#type-param-T_SPLITR" title="type parameter in Spliterator.OfPrimitive">T_SPLITR extends <\ a href="Spliterator.OfPrimitive.html" title="interface in pkg2">Spliterator.OfPr\ - imitive<T,<T,T_CONS,T_SPLITRT_SPLITR>>
 
"""); diff --git a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java new file mode 100644 index 00000000000..5cb1f687d45 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8313931 + * @summary Javadoc: links to type parameters actually generate links to classes + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestLinkTagletTypeParam + */ + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +import java.io.IOException; +import java.nio.file.Path; + +public class TestLinkTagletTypeParam extends JavadocTester { + + public static void main(String... args) throws Exception { + var tester = new TestLinkTagletTypeParam(); + tester.runTests(); + } + + ToolBox tb = new ToolBox(); + + @JavadocTester.Test + public void testClassTypeParameterLink(Path base) throws IOException { + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + """ + /** + * Link to {@link F}. + * + * @param the first type param + * @param an Appendable + * + * @see APND the second type parameter + */ + public class Test { + private Test() {} + } + """); + + javadoc("-Xdoclint:none", + "-d", base.resolve("api").toString(), + "-sourcepath", src.toString(), + src.resolve("Test.java").toString()); + checkExit(JavadocTester.Exit.OK); + + checkOrder("Test.html", + """ +
Type Parameters:
+
F - the first type param
+
APND - an Appendable
""", + """ + Link to
F.""", + """ +
See Also:
+
+ """); + } + + @JavadocTester.Test + public void testMethodTypeParameterLink(Path base) throws IOException { + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + """ + /** + * Class comment. + */ + public class Test { + /** + * Link to {@link T} and {@linkplain T link with label}. + * + * @param the T + * @param appendable the appendable + */ + public T append(final T appendable) { + return appendable; + } + } + """); + + javadoc("-Xdoclint:reference", + "-d", base.resolve("api").toString(), + "-sourcepath", src.toString(), + src.resolve("Test.java").toString()); + + checkOutput(JavadocTester.Output.OUT, true, + ""); + + checkOutput("Test.html", true, + """ + Link to T and link with label."""); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java index 705cae327e3..559f7b08d38 100644 --- a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,8 +120,8 @@ interface in pkg">BaseInterface
checkOutput("pkg2/DocumentedNonGenericChild.html", true, """
-

+
public abstract class DocumentedNonGenericChild extends java.lang.Object
diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java index 79bad12f95d..4d3628544f8 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java @@ -1360,8 +1360,8 @@ void checkLinkSource(boolean includePrivate) { checkOutput("moduleA/testpkgmdlA/TestClassInModuleA.html", true, """
-

+
public class TestClassInModuleA diff --git a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java index a54fbbcff75..eafad8c3245 100644 --- a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,7 +117,7 @@ void checkTypeParameters() { // Check class type parameters section. """
Type Parameters:
-
E - the type parameter for this class.""", +
E - the type parameter for this class.
""", // Type parameters in @see/@link """
@@ -130,12 +130,14 @@ void checkTypeParameters() {
""", // Method that uses class type parameter. """ - (E param)""", + (E param)""", // Method type parameter section. """
Type Parameters:
-
T - This is the first type parameter.
-
V - This is the second type parameter.""", +
T - Th\ + is is the first type parameter.
+
V - Th\ + is is the second type parameter.
""", // Signature of method with type parameters """
public E[]
methodThatReturnsTypeParameterA(E[] \ + ref="#type-param-E" title="type parameter in TypeParameters">E[] \ e)""", """
public E[] methodThatReturnsTypePa\ - rameterA((E[] e)
""", """ @@ -176,7 +178,7 @@ void checkTypeParameters() { """
<X extends java.lang.Throwable>
E
\ + href="#type-param-E" title="type parameter in TypeParameters">E
\
Type Parameters: -
T2 - type 2
+
T2 - type 2
Parameters:
t1 - param 1
t3 - param 3
@@ -92,7 +92,7 @@ public void test() { checkOutput("pkg/C.Nested.html", true, """
Type Parameters:
-
T1 - type 1
+
T1 - type 1
"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java index 7ce046c0757..94ad1a8040f 100644 --- a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java +++ b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,7 +110,7 @@ class in pkg">ObjectProperty
<public final <\ span class="return-type">Obje\ - ctProperty<java.util.List<T>> listProperty<\ /div>
This is an Object property where the Object is a single List<T>.
diff --git a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java index f9aa3cfd6fa..3b6a8a4fc72 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java @@ -175,7 +175,7 @@ public record R(int r1) { }"""); """
Type Parameters:
-
T - This is a type parameter.
+
T - This is a type parameter.
Record Components:
r1 - This is a component.
""", diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java index 9bf2ac362c6..af3e36aa7d8 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -219,6 +219,7 @@ public void test2() { """ Fields[] singleArray""", """ - java.lang.Class<E> someClass"""); + java.lang.Class<E> someClass"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java index ca4592ea5f8..e4c57857899 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java +++ b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,7 @@ public interface C { """
Type Parameters:
-
T - the throwable
+
T - the throwable
Throws:
T - if a specific error occurs
java.lang.Exception - if an exception occurs
diff --git a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java index 0d95ee38cdc..dad610acb30 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4927167 4974929 6381729 7010344 8025633 8081854 8182765 8187288 8261976 + * @bug 4927167 4974929 6381729 7010344 8025633 8081854 8182765 8187288 8261976 8313931 * @summary When the type parameters are more than 10 characters in length, * make sure there is a line break between type params and return type * in member summary. Also, test for type parameter links in package-summary and @@ -110,10 +110,22 @@ public void test3() {
 <T extends java.lang.Runnable>
-
 
""", +
+
Generic constructor.
""", """
public\  <T extends java.lang.Runnable>\ -  CtorTypeParam()
"""); +  CtorTypeParam()
""", + """ + T""", + """ +
Type Parameters:
+
T - the type parameter
""", + """ +
See Also:
+
+ """); } } diff --git a/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java b/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java index a7f2309475d..690471861db 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java @@ -24,6 +24,12 @@ package pkg; public class CtorTypeParam { + /** + * Generic constructor. {@link T} + * + * @param the type parameter + * @see T link to type parameter + */ public CtorTypeParam() { } } diff --git a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java index 76008260343..cf30488ec7b 100644 --- a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java +++ b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ public class Code<##> { """
Type Parameters:
-
## - the ##
+
## - the ##
""".replaceAll("##", chineseElephant), """ From 2b5aec2aad3883d4d407ec3a572f78755d60190d Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Fri, 9 Aug 2024 11:28:59 +0000 Subject: [PATCH 27/84] 8338109: java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java duplicate in ProblemList Reviewed-by: aivanov --- test/jdk/ProblemList.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 293d9d108d3..6cde7111383 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -375,7 +375,7 @@ java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665 macosx-all java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326 macosx-all -java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021 macosx-all +java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021,8332158 macosx-all,linux-x64 java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java 7124407,8302787 macosx-all,windows-all java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java 8157170 macosx-all @@ -475,7 +475,6 @@ java/awt/Choice/SelectNewItemTest/SelectNewItemTest.java 8324782 macosx-all # Wayland related -java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8332158 linux-x64 java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64 java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64 From 069e0ea69f43960164d3e077d2c7b950cde77927 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 9 Aug 2024 12:00:15 +0000 Subject: [PATCH 28/84] 8338064: Give better error for ConcurrentHashTable corruption Reviewed-by: dholmes, shade --- .../share/utilities/concurrentHashTable.hpp | 5 ++ .../utilities/concurrentHashTable.inline.hpp | 6 +- .../StringTableCorruptionTest.java | 59 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index 991ea9fe3c6..4e506d5fe84 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -65,6 +65,7 @@ class ConcurrentHashTable : public CHeapObj { // the InternalTable or user-defined memory. class Node { private: + DEBUG_ONLY(size_t _saved_hash); Node * volatile _next; VALUE _value; public: @@ -77,6 +78,10 @@ class ConcurrentHashTable : public CHeapObj { Node* next() const; void set_next(Node* node) { _next = node; } Node* const volatile * next_ptr() { return &_next; } +#ifdef ASSERT + size_t saved_hash() const { return _saved_hash; } + void set_saved_hash(size_t hash) { _saved_hash = hash; } +#endif VALUE* value() { return &_value; } diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index 78c7e148bbb..f035aeae448 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -679,7 +679,9 @@ inline bool ConcurrentHashTable:: // Keep in odd list odd = aux->next_ptr(); } else { - fatal("aux_index does not match even or odd indices"); + const char* msg = "Cannot resize table: Node hash code has changed possibly due to corruption of the contents."; + DEBUG_ONLY(fatal("%s Node hash code changed from " SIZE_FORMAT " to " SIZE_FORMAT, msg, aux->saved_hash(), aux_hash);) + NOT_DEBUG(fatal("%s", msg);) } } aux = aux_next; @@ -892,6 +894,7 @@ inline bool ConcurrentHashTable:: size_t i = 0; uintx hash = lookup_f.get_hash(); Node* new_node = Node::create_node(_context, value, nullptr); + DEBUG_ONLY(new_node->set_saved_hash(hash);) while (true) { { @@ -1117,6 +1120,7 @@ inline bool ConcurrentHashTable:: Bucket* bucket = get_bucket_in(table, hash); assert(!bucket->have_redirect() && !bucket->is_locked(), "bad"); Node* new_node = Node::create_node(_context, value, bucket->first()); + DEBUG_ONLY(new_node->set_saved_hash(hash);) if (!bucket->cas_first(new_node, bucket->first())) { assert(false, "bad"); } diff --git a/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java new file mode 100644 index 00000000000..e4d6a2e5d0f --- /dev/null +++ b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8333356 + * @summary Verify new error message for corrupting string table contents. + * @requires vm.flagless + * @modules java.base/java.lang:open + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @run driver StringTableCorruptionTest test + */ + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class StringTableCorruptionTest { + public static void main(String[] args) throws Exception { + if (args.length > 0) { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("--add-opens", "java.base/java.lang=ALL-UNNAMED", + "-XX:-CreateCoredumpOnCrash", "StringTableCorruptionTest"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Node hash code has changed possibly due to corruption of the contents."); + output.shouldNotHaveExitValue(0); + return; + } + + Field f = String.class.getDeclaredField("value"); + f.setAccessible(true); + f.set("s1".intern(), f.get("s2")); + for (int i = 0; i < 4_000_000; i++) { + ("s_" + i).intern(); + } + } +} From 3cf3f300de1e9d2c8767877ed3a26679e34b7d22 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Fri, 9 Aug 2024 14:32:29 +0000 Subject: [PATCH 29/84] 8330191: Fix typo in precompiled.hpp Reviewed-by: jsjolen, szaldana --- src/hotspot/share/precompiled/precompiled.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/precompiled/precompiled.hpp b/src/hotspot/share/precompiled/precompiled.hpp index c53a78de87b..07922d12969 100644 --- a/src/hotspot/share/precompiled/precompiled.hpp +++ b/src/hotspot/share/precompiled/precompiled.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ // These header files are included in at least 130 C++ files, as of // measurements made in November 2018. This list excludes files named -// *.include.hpp, since including them decreased build performance. +// *.inline.hpp, since including them decreased build performance. #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" From 60fa08fcfe5c6551ee3120330ade93e45df618c7 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 9 Aug 2024 17:08:19 +0000 Subject: [PATCH 30/84] 8337797: Additional ExternalAddress cleanup Reviewed-by: adinn, thartmann --- src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp | 4 ++-- src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp | 9 ++------- src/hotspot/cpu/x86/assembler_x86.cpp | 1 + src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp | 8 ++++---- src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp | 6 +++--- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 4 ++-- src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 4 ++-- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 4 ++-- src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp | 2 +- src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp | 4 ++-- 10 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp index e79b93651b0..aea268ea944 100644 --- a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -201,7 +201,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { { __ enter(); - __ lea(rscratch1, ExternalAddress(slow_case_addr)); + __ lea(rscratch1, RuntimeAddress(slow_case_addr)); __ blr(rscratch1); __ leave(); __ ret(lr); diff --git a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp index 8423ecad8a3..f7d702c6310 100644 --- a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp +++ b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -173,12 +173,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { { __ enter(); - ExternalAddress target(slow_case_addr); - __ relocate(target.rspec(), [&] { - int32_t offset; - __ la(t0, target.target(), offset); - __ jalr(t0, offset); - }); + __ rt_call(slow_case_addr); __ leave(); __ ret(); } diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 001ff472f40..207d3fbb61e 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -1780,6 +1780,7 @@ void Assembler::call(Register dst) { void Assembler::call(Address adr) { + assert(!adr._rspec.reloc()->is_data(), "should not use ExternalAddress for call"); InstructionMark im(this); prefix(adr); emit_int8((unsigned char)0xFF); diff --git a/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp b/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp index 34be2a61b5a..52e4388c5d2 100644 --- a/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp +++ b/src/hotspot/cpu/x86/jniFastGetField_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,7 +138,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { default: ShouldNotReachHere(); } // tail call - __ jump (ExternalAddress(slow_case_addr)); + __ jump (RuntimeAddress(slow_case_addr)); __ flush (); @@ -251,7 +251,7 @@ address JNI_FastGetField::generate_fast_get_long_field() { __ pop (rsi); address slow_case_addr = jni_GetLongField_addr();; // tail call - __ jump (ExternalAddress(slow_case_addr)); + __ jump (RuntimeAddress(slow_case_addr)); __ flush (); @@ -350,7 +350,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { default: ShouldNotReachHere(); } // tail call - __ jump (ExternalAddress(slow_case_addr)); + __ jump (RuntimeAddress(slow_case_addr)); __ flush (); diff --git a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp index 4506205c259..e94b7d12b0b 100644 --- a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp +++ b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,7 +118,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { default: break; } // tail call - __ jump (ExternalAddress(slow_case_addr), rscratch1); + __ jump (RuntimeAddress(slow_case_addr), rscratch1); __ flush (); @@ -206,7 +206,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { default: break; } // tail call - __ jump (ExternalAddress(slow_case_addr), rscratch1); + __ jump (RuntimeAddress(slow_case_addr), rscratch1); __ flush (); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index affd18f937c..c8234d6b9b8 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -2329,7 +2329,7 @@ void MacroAssembler::incrementl(Address dst, int value) { void MacroAssembler::jump(AddressLiteral dst, Register rscratch) { assert(rscratch != noreg || always_reachable(dst), "missing"); - + assert(!dst.rspec().reloc()->is_data(), "should not use ExternalAddress for jump"); if (reachable(dst)) { jmp_literal(dst.target(), dst.rspec()); } else { @@ -2340,7 +2340,7 @@ void MacroAssembler::jump(AddressLiteral dst, Register rscratch) { void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst, Register rscratch) { assert(rscratch != noreg || always_reachable(dst), "missing"); - + assert(!dst.rspec().reloc()->is_data(), "should not use ExternalAddress for jump_cc"); if (reachable(dst)) { InstructionMark im(this); relocate(dst.reloc()); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index 80be7c7d5b6..d313c1b216a 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -704,10 +704,10 @@ static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg address code_start, address code_end, Label& L_ok) { Label L_fail; - __ lea(temp_reg, ExternalAddress(code_start)); + __ lea(temp_reg, AddressLiteral(code_start, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::belowEqual, L_fail); - __ lea(temp_reg, ExternalAddress(code_end)); + __ lea(temp_reg, AddressLiteral(code_end, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::below, L_ok); __ bind(L_fail); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index f2488ef4e74..d27b1d141fc 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -824,10 +824,10 @@ static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg address code_start, address code_end, Label& L_ok) { Label L_fail; - __ lea(temp_reg, ExternalAddress(code_start)); + __ lea(temp_reg, AddressLiteral(code_start, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::belowEqual, L_fail); - __ lea(temp_reg, ExternalAddress(code_end)); + __ lea(temp_reg, AddressLiteral(code_end, relocInfo::none)); __ cmpptr(pc_reg, temp_reg); __ jcc(Assembler::below, L_ok); __ bind(L_fail); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp index d8f7a6b272b..5b316881d03 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_arraycopy.cpp @@ -215,7 +215,7 @@ void StubGenerator::array_overlap_test(address no_overlap_target, Label* NOLp, A __ cmpptr(to, from); __ lea(end_from, Address(from, count, sf, 0)); if (NOLp == nullptr) { - ExternalAddress no_overlap(no_overlap_target); + RuntimeAddress no_overlap(no_overlap_target); __ jump_cc(Assembler::belowEqual, no_overlap); __ cmpptr(to, end_from); __ jump_cc(Assembler::aboveEqual, no_overlap); diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 7e0814c014b..62022d780a2 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,7 +180,7 @@ bool os::win32::register_code_area(char *low, char *high) { MacroAssembler* masm = new MacroAssembler(&cb); pDCD = (pDynamicCodeData) masm->pc(); - masm->jump(ExternalAddress((address)&HandleExceptionFromCodeCache), rscratch1); + masm->jump(RuntimeAddress((address)&HandleExceptionFromCodeCache), rscratch1); masm->flush(); // Create an Unwind Structure specifying no unwind info From 358d77dafbe0e35d5b20340fccddc0fb8f3db82a Mon Sep 17 00:00:00 2001 From: Dmitry Chuyko Date: Fri, 9 Aug 2024 17:56:37 +0000 Subject: [PATCH 31/84] 8337657: AArch64: No need for acquire fence in safepoint poll during JNI calls Reviewed-by: phh --- src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp | 12 ++---------- .../aarch64/templateInterpreterGenerator_aarch64.cpp | 11 ++--------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 65c026b95ab..8ce4230baa2 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1883,16 +1883,8 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Check for safepoint operation in progress and/or pending suspend requests. { - // We need an acquire here to ensure that any subsequent load of the - // global SafepointSynchronize::_state flag is ordered after this load - // of the thread-local polling word. We don't want this poll to - // return false (i.e. not safepointing) and a later poll of the global - // SafepointSynchronize::_state spuriously to return true. - // - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. - - __ safepoint_poll(safepoint_in_progress, true /* at_return */, true /* acquire */, false /* in_nmethod */); + // No need for acquire as Java threads always disarm themselves. + __ safepoint_poll(safepoint_in_progress, true /* at_return */, false /* acquire */, false /* in_nmethod */); __ ldrw(rscratch1, Address(rthread, JavaThread::suspend_flags_offset())); __ cbnzw(rscratch1, safepoint_in_progress); __ bind(safepoint_in_progress_done); diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index d639d9cf17e..ed2450a9110 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1413,15 +1413,8 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { { Label L, Continue; - // We need an acquire here to ensure that any subsequent load of the - // global SafepointSynchronize::_state flag is ordered after this load - // of the thread-local polling word. We don't want this poll to - // return false (i.e. not safepointing) and a later poll of the global - // SafepointSynchronize::_state spuriously to return true. - // - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. - __ safepoint_poll(L, true /* at_return */, true /* acquire */, false /* in_nmethod */); + // No need for acquire as Java threads always disarm themselves. + __ safepoint_poll(L, true /* at_return */, false /* acquire */, false /* in_nmethod */); __ ldrw(rscratch2, Address(rthread, JavaThread::suspend_flags_offset())); __ cbz(rscratch2, Continue); __ bind(L); From 6a3d045221c338fefec9bd59245324eae60b156b Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Sun, 11 Aug 2024 18:34:18 +0000 Subject: [PATCH 32/84] 8337709: Use allocated states for chunking large array processing Reviewed-by: iwalulya, tschatzl --- .../share/gc/g1/g1ParScanThreadState.cpp | 90 +++++++---- .../share/gc/g1/g1ParScanThreadState.hpp | 12 +- .../share/gc/shared/partialArrayState.cpp | 152 ++++++++++++++++++ .../share/gc/shared/partialArrayState.hpp | 136 ++++++++++++++++ .../gc/shared/partialArrayTaskStepper.cpp | 6 +- .../gc/shared/partialArrayTaskStepper.hpp | 59 ++++--- .../shared/partialArrayTaskStepper.inline.hpp | 71 +++----- src/hotspot/share/gc/shared/taskqueue.hpp | 21 ++- .../shared/test_partialArrayTaskStepper.cpp | 42 ++--- 9 files changed, 444 insertions(+), 145 deletions(-) create mode 100644 src/hotspot/share/gc/shared/partialArrayState.cpp create mode 100644 src/hotspot/share/gc/shared/partialArrayState.hpp diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index e4ac20ca7ea..f81c3241a1a 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -35,6 +35,7 @@ #include "gc/g1/g1Trace.hpp" #include "gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp" #include "gc/shared/continuationGCSupport.inline.hpp" +#include "gc/shared/partialArrayState.hpp" #include "gc/shared/partialArrayTaskStepper.inline.hpp" #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" @@ -43,6 +44,7 @@ #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/mutexLocker.hpp" #include "runtime/prefetch.inline.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -61,7 +63,8 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, uint num_workers, G1CollectionSet* collection_set, - G1EvacFailureRegions* evac_failure_regions) + G1EvacFailureRegions* evac_failure_regions, + PartialArrayStateAllocator* pas_allocator) : _g1h(g1h), _task_queue(g1h->task_queue(worker_id)), _rdc_local_qset(rdcqs), @@ -80,8 +83,8 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, _surviving_young_words(nullptr), _surviving_words_length(collection_set->young_region_length() + 1), _old_gen_is_full(false), - _partial_objarray_chunk_size(ParGCArrayScanChunk), - _partial_array_stepper(num_workers), + _partial_array_state_allocator(pas_allocator), + _partial_array_stepper(num_workers, ParGCArrayScanChunk), _string_dedup_requests(), _max_num_optional_regions(collection_set->optional_region_length()), _numa(g1h->numa()), @@ -169,9 +172,9 @@ void G1ParScanThreadState::verify_task(oop* task) const { "task=" PTR_FORMAT " p=" PTR_FORMAT, p2i(task), p2i(p)); } -void G1ParScanThreadState::verify_task(PartialArrayScanTask task) const { +void G1ParScanThreadState::verify_task(PartialArrayState* task) const { // Must be in the collection set--it's already been copied. - oop p = task.to_source_array(); + oop p = task->source(); assert(_g1h->is_in_cset(p), "p=" PTR_FORMAT, p2i(p)); } @@ -180,8 +183,8 @@ void G1ParScanThreadState::verify_task(ScannerTask task) const { verify_task(task.to_narrow_oop_ptr()); } else if (task.is_oop_ptr()) { verify_task(task.to_oop_ptr()); - } else if (task.is_partial_array_task()) { - verify_task(task.to_partial_array_task()); + } else if (task.is_partial_array_state()) { + verify_task(task.to_partial_array_state()); } else { ShouldNotReachHere(); } @@ -223,34 +226,39 @@ void G1ParScanThreadState::do_oop_evac(T* p) { } MAYBE_INLINE_EVACUATION -void G1ParScanThreadState::do_partial_array(PartialArrayScanTask task) { - oop from_obj = task.to_source_array(); +void G1ParScanThreadState::do_partial_array(PartialArrayState* state) { + oop to_obj = state->destination(); +#ifdef ASSERT + oop from_obj = state->source(); assert(_g1h->is_in_reserved(from_obj), "must be in heap."); assert(from_obj->is_objArray(), "must be obj array"); assert(from_obj->is_forwarded(), "must be forwarded"); - - oop to_obj = from_obj->forwardee(); assert(from_obj != to_obj, "should not be chunking self-forwarded objects"); assert(to_obj->is_objArray(), "must be obj array"); +#endif // ASSERT + objArrayOop to_array = objArrayOop(to_obj); - PartialArrayTaskStepper::Step step - = _partial_array_stepper.next(objArrayOop(from_obj), - to_array, - _partial_objarray_chunk_size); - for (uint i = 0; i < step._ncreate; ++i) { - push_on_queue(ScannerTask(PartialArrayScanTask(from_obj))); + // Claim a chunk and get number of additional tasks to enqueue. + PartialArrayTaskStepper::Step step = _partial_array_stepper.next(state); + // Push any additional partial scan tasks needed. Pushed before processing + // the claimed chunk to allow other workers to steal while we're processing. + if (step._ncreate > 0) { + state->add_references(step._ncreate); + for (uint i = 0; i < step._ncreate; ++i) { + push_on_queue(ScannerTask(state)); + } } G1HeapRegionAttr dest_attr = _g1h->region_attr(to_array); G1SkipCardEnqueueSetter x(&_scanner, dest_attr.is_new_survivor()); - // Process claimed task. The length of to_array is not correct, but - // fortunately the iteration ignores the length field and just relies - // on start/end. + // Process claimed task. to_array->oop_iterate_range(&_scanner, - step._index, - step._index + _partial_objarray_chunk_size); + checked_cast(step._index), + checked_cast(step._index + _partial_array_stepper.chunk_size())); + // Release reference to the state, now that we're done with it. + _partial_array_state_allocator->release(_worker_id, state); } MAYBE_INLINE_EVACUATION @@ -260,20 +268,30 @@ void G1ParScanThreadState::start_partial_objarray(G1HeapRegionAttr dest_attr, assert(from_obj->is_objArray(), "precondition"); assert(from_obj->is_forwarded(), "precondition"); assert(from_obj->forwardee() == to_obj, "precondition"); - assert(from_obj != to_obj, "should not be scanning self-forwarded objects"); assert(to_obj->is_objArray(), "precondition"); objArrayOop to_array = objArrayOop(to_obj); - PartialArrayTaskStepper::Step step - = _partial_array_stepper.start(objArrayOop(from_obj), - to_array, - _partial_objarray_chunk_size); + size_t array_length = to_array->length(); + PartialArrayTaskStepper::Step step = _partial_array_stepper.start(array_length); // Push any needed partial scan tasks. Pushed before processing the // initial chunk to allow other workers to steal while we're processing. - for (uint i = 0; i < step._ncreate; ++i) { - push_on_queue(ScannerTask(PartialArrayScanTask(from_obj))); + if (step._ncreate > 0) { + assert(step._index < array_length, "invariant"); + assert(((array_length - step._index) % _partial_array_stepper.chunk_size()) == 0, + "invariant"); + PartialArrayState* state = + _partial_array_state_allocator->allocate(_worker_id, + from_obj, to_obj, + step._index, + array_length, + step._ncreate); + for (uint i = 0; i < step._ncreate; ++i) { + push_on_queue(ScannerTask(state)); + } + } else { + assert(step._index == array_length, "invariant"); } // Skip the card enqueue iff the object (to_array) is in survivor region. @@ -284,9 +302,8 @@ void G1ParScanThreadState::start_partial_objarray(G1HeapRegionAttr dest_attr, G1SkipCardEnqueueSetter x(&_scanner, dest_attr.is_young()); // Process the initial chunk. No need to process the type in the // klass, as it will already be handled by processing the built-in - // module. The length of to_array is not correct, but fortunately - // the iteration ignores that length field and relies on start/end. - to_array->oop_iterate_range(&_scanner, 0, step._index); + // module. + to_array->oop_iterate_range(&_scanner, 0, checked_cast(step._index)); } MAYBE_INLINE_EVACUATION @@ -297,7 +314,7 @@ void G1ParScanThreadState::dispatch_task(ScannerTask task) { } else if (task.is_oop_ptr()) { do_oop_evac(task.to_oop_ptr()); } else { - do_partial_array(task.to_partial_array_task()); + do_partial_array(task.to_partial_array_state()); } } @@ -582,7 +599,8 @@ G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id) worker_id, _num_workers, _collection_set, - _evac_failure_regions); + _evac_failure_regions, + &_partial_array_state_allocator); } return _states[worker_id]; } @@ -715,7 +733,9 @@ G1ParScanThreadStateSet::G1ParScanThreadStateSet(G1CollectedHeap* g1h, _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, collection_set->young_region_length() + 1, mtGC)), _num_workers(num_workers), _flushed(false), - _evac_failure_regions(evac_failure_regions) { + _evac_failure_regions(evac_failure_regions), + _partial_array_state_allocator(num_workers) +{ _preserved_marks_set.init(num_workers); for (uint i = 0; i < num_workers; ++i) { _states[i] = nullptr; diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 24ca682e141..1cfd6fca08a 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -32,6 +32,7 @@ #include "gc/shared/ageTable.hpp" #include "gc/shared/copyFailedInfo.hpp" #include "gc/shared/gc_globals.hpp" +#include "gc/shared/partialArrayState.hpp" #include "gc/shared/partialArrayTaskStepper.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" @@ -87,7 +88,8 @@ class G1ParScanThreadState : public CHeapObj { // available for allocation. bool _old_gen_is_full; // Size (in elements) of a partial objArray task chunk. - int _partial_objarray_chunk_size; + size_t _partial_objarray_chunk_size; + PartialArrayStateAllocator* _partial_array_state_allocator; PartialArrayTaskStepper _partial_array_stepper; StringDedup::Requests _string_dedup_requests; @@ -129,7 +131,8 @@ class G1ParScanThreadState : public CHeapObj { uint worker_id, uint num_workers, G1CollectionSet* collection_set, - G1EvacFailureRegions* evac_failure_regions); + G1EvacFailureRegions* evac_failure_regions, + PartialArrayStateAllocator* partial_array_state_allocator); virtual ~G1ParScanThreadState(); void set_ref_discoverer(ReferenceDiscoverer* rd) { _scanner.set_ref_discoverer(rd); } @@ -140,7 +143,7 @@ class G1ParScanThreadState : public CHeapObj { void verify_task(narrowOop* task) const NOT_DEBUG_RETURN; void verify_task(oop* task) const NOT_DEBUG_RETURN; - void verify_task(PartialArrayScanTask task) const NOT_DEBUG_RETURN; + void verify_task(PartialArrayState* task) const NOT_DEBUG_RETURN; void verify_task(ScannerTask task) const NOT_DEBUG_RETURN; void push_on_queue(ScannerTask task); @@ -169,7 +172,7 @@ class G1ParScanThreadState : public CHeapObj { size_t flush_stats(size_t* surviving_young_words, uint num_workers, BufferNodeList* buffer_log); private: - void do_partial_array(PartialArrayScanTask task); + void do_partial_array(PartialArrayState* state); void start_partial_objarray(G1HeapRegionAttr dest_dir, oop from, oop to); HeapWord* allocate_copy_slow(G1HeapRegionAttr* dest_attr, @@ -252,6 +255,7 @@ class G1ParScanThreadStateSet : public StackObj { uint _num_workers; bool _flushed; G1EvacFailureRegions* _evac_failure_regions; + PartialArrayStateAllocator _partial_array_state_allocator; public: G1ParScanThreadStateSet(G1CollectedHeap* g1h, diff --git a/src/hotspot/share/gc/shared/partialArrayState.cpp b/src/hotspot/share/gc/shared/partialArrayState.cpp new file mode 100644 index 00000000000..583c5dede40 --- /dev/null +++ b/src/hotspot/share/gc/shared/partialArrayState.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/shared/partialArrayState.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/arena.hpp" +#include "nmt/memflags.hpp" +#include "oops/oopsHierarchy.hpp" +#include "runtime/atomic.hpp" +#include "runtime/orderAccess.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" +#include + +PartialArrayState::PartialArrayState(oop src, oop dst, + size_t index, size_t length, + size_t initial_refcount) + : _source(src), + _destination(dst), + _length(length), + _index(index), + _refcount(initial_refcount) +{ + assert(index <= length, "precondition"); +} + +void PartialArrayState::add_references(size_t count) { + size_t new_count = Atomic::add(&_refcount, count, memory_order_relaxed); + assert(new_count >= count, "reference count overflow"); +} + +class PartialArrayStateAllocator::Impl : public CHeapObj { + struct FreeListEntry; + + Arena* _arenas; + FreeListEntry** _free_lists; + uint _num_workers; + +public: + Impl(uint num_workers); + ~Impl(); + + NONCOPYABLE(Impl); + + PartialArrayState* allocate(uint worker_id, + oop src, oop dst, + size_t index, size_t length, + size_t initial_refcount); + void release(uint worker_id, PartialArrayState* state); +}; + +struct PartialArrayStateAllocator::Impl::FreeListEntry { + FreeListEntry* _next; + + FreeListEntry(FreeListEntry* next) : _next(next) {} + ~FreeListEntry() = default; + + NONCOPYABLE(FreeListEntry); +}; + +PartialArrayStateAllocator::Impl::Impl(uint num_workers) + : _arenas(NEW_C_HEAP_ARRAY(Arena, num_workers, mtGC)), + _free_lists(NEW_C_HEAP_ARRAY(FreeListEntry*, num_workers, mtGC)), + _num_workers(num_workers) +{ + for (uint i = 0; i < _num_workers; ++i) { + ::new (&_arenas[i]) Arena(mtGC); + _free_lists[i] = nullptr; + } +} + +PartialArrayStateAllocator::Impl::~Impl() { + // We don't need to clean up the free lists. Deallocating the entries + // does nothing, since we're using arena allocation. Instead, leave it + // to the arena destructor to release the memory. + FREE_C_HEAP_ARRAY(FreeListEntry*, _free_lists); + for (uint i = 0; i < _num_workers; ++i) { + _arenas[i].~Arena(); + } +} + +PartialArrayState* PartialArrayStateAllocator::Impl::allocate(uint worker_id, + oop src, oop dst, + size_t index, + size_t length, + size_t initial_refcount) { + void* p; + FreeListEntry* head = _free_lists[worker_id]; + if (head == nullptr) { + p = NEW_ARENA_OBJ(&_arenas[worker_id], PartialArrayState); + } else { + _free_lists[worker_id] = head->_next; + head->~FreeListEntry(); + p = head; + } + return ::new (p) PartialArrayState(src, dst, index, length, initial_refcount); +} + +void PartialArrayStateAllocator::Impl::release(uint worker_id, PartialArrayState* state) { + size_t refcount = Atomic::sub(&state->_refcount, size_t(1), memory_order_release); + if (refcount != 0) { + assert(refcount + 1 != 0, "refcount underflow"); + } else { + OrderAccess::acquire(); + state->~PartialArrayState(); + _free_lists[worker_id] = ::new (state) FreeListEntry(_free_lists[worker_id]); + } +} + +PartialArrayStateAllocator::PartialArrayStateAllocator(uint num_workers) + : _impl(new Impl(num_workers)) +{} + +PartialArrayStateAllocator::~PartialArrayStateAllocator() { + delete _impl; +} + +PartialArrayState* PartialArrayStateAllocator::allocate(uint worker_id, + oop src, oop dst, + size_t index, + size_t length, + size_t initial_refcount) { + return _impl->allocate(worker_id, src, dst, index, length, initial_refcount); +} + +void PartialArrayStateAllocator::release(uint worker_id, PartialArrayState* state) { + _impl->release(worker_id, state); +} + diff --git a/src/hotspot/share/gc/shared/partialArrayState.hpp b/src/hotspot/share/gc/shared/partialArrayState.hpp new file mode 100644 index 00000000000..f3bfc3ed8b8 --- /dev/null +++ b/src/hotspot/share/gc/shared/partialArrayState.hpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_GC_SHARED_PARTIALARRAYSTATE_HPP +#define SHARE_GC_SHARED_PARTIALARRAYSTATE_HPP + +#include "oops/oopsHierarchy.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +class PartialArrayStateAllocator; + +// Instances of this class are used to represent processing progress for an +// array task in a taskqueue. When a sufficiently large array needs to be +// processed, such that it is desirable to split up the processing into +// parallelizable subtasks, a state object is allocated for the array. +// Multiple tasks referring to the state can then be added to the taskqueue +// for later processing, either by the current thread or by some other thread +// that steals one of those tasks. +// +// Processing a state involves using the state to claim a segment of the +// array, and processing that segment. Claiming is done by atomically +// incrementing the index, thereby claiming the segment from the old to new +// index values. New tasks should also be added as needed to ensure the +// entire array will be processed. A PartialArrayTaskStepper can be used to +// help with this. +// +// States are allocated and released using a PartialArrayStateAllocator. +// States are reference counted to aid in that management. Each task +// referring to a given state that is added to a taskqueue must increase the +// reference count by one. When the processing of a task referring to a state +// is complete, the reference count must be decreased by one. When the +// reference count reaches zero the state should be released to the allocator +// for later reuse. +class PartialArrayState { + oop _source; + oop _destination; + size_t _length; + volatile size_t _index; + volatile size_t _refcount; + + friend class PartialArrayStateAllocator; + + PartialArrayState(oop src, oop dst, + size_t index, size_t length, + size_t initial_refcount); + ~PartialArrayState() = default; + + NONCOPYABLE(PartialArrayState); + +public: + // Add count references, one per referring task being added to a taskqueue. + void add_references(size_t count); + + // The source array oop. + oop source() const { return _source; } + + // The destination array oop. In some circumstances the source and + // destination may be the same. + oop destination() const { return _destination; } + + // The length of the array oop. + size_t length() const { return _length; } + + // A pointer to the start index for the next segment to process, for atomic + // update. + volatile size_t* index_addr() { return &_index; } +}; + +// This class provides memory management for PartialArrayStates. +// +// States are initially allocated from a set of arenas owned by the allocator. +// This allows the entire set of allocated states to be discarded without the +// need to keep track of or find them under some circumstances. For example, +// if G1 concurrent marking is aborted and needs to restart because of a full +// marking queue, the queue doesn't need to be searched for tasks referring to +// states to allow releasing them. Instead the queue contents can just be +// discarded, and the memory for the no longer referenced states will +// eventually be reclaimed when the arenas are reset. +// +// A set of free-lists is placed in front of the arena allocators. This +// causes the maximum number of allocated states to be based on the number of +// in-progress arrays, rather than the total number of arrays that need to be +// processed. The use of free-list allocators is the reason for reference +// counting states. +// +// The arena and free-list to use for an allocation operation is designated by +// the worker_id used in the operation. This avoids locking and such on those +// data structures, at the cost of possibly doing more total arena allocation +// that would be needed with a single shared arena and free-list. +class PartialArrayStateAllocator { + class Impl; + Impl* _impl; + +public: + PartialArrayStateAllocator(uint num_workers); + ~PartialArrayStateAllocator(); + + NONCOPYABLE(PartialArrayStateAllocator); + + // Create a new state, obtaining the memory for it from the free-list or + // arena associated with worker_id. + PartialArrayState* allocate(uint worker_id, + oop src, oop dst, + size_t index, size_t length, + size_t initial_refcount); + + // Decrement the state's refcount. If the new refcount is zero, add the + // state to the free-list associated with worker_id. The state must have + // been allocated by this allocator, but that allocation doesn't need to + // have been associated with worker_id. + void release(uint worker_id, PartialArrayState* state); +}; + +#endif // SHARE_GC_SHARED_PARTIALARRAYSTATE_HPP diff --git a/src/hotspot/share/gc/shared/partialArrayTaskStepper.cpp b/src/hotspot/share/gc/shared/partialArrayTaskStepper.cpp index ed52d7abff1..6faa162ac7b 100644 --- a/src/hotspot/share/gc/shared/partialArrayTaskStepper.cpp +++ b/src/hotspot/share/gc/shared/partialArrayTaskStepper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc/shared/partialArrayTaskStepper.hpp" #include "oops/arrayOop.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/powerOfTwo.hpp" @@ -48,7 +49,8 @@ static uint compute_task_fanout(uint task_limit) { return result; } -PartialArrayTaskStepper::PartialArrayTaskStepper(uint n_workers) : +PartialArrayTaskStepper::PartialArrayTaskStepper(uint n_workers, size_t chunk_size) : + _chunk_size(chunk_size), _task_limit(compute_task_limit(n_workers)), _task_fanout(compute_task_fanout(_task_limit)) {} diff --git a/src/hotspot/share/gc/shared/partialArrayTaskStepper.hpp b/src/hotspot/share/gc/shared/partialArrayTaskStepper.hpp index aec993f907c..a68d9bd3612 100644 --- a/src/hotspot/share/gc/shared/partialArrayTaskStepper.hpp +++ b/src/hotspot/share/gc/shared/partialArrayTaskStepper.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,55 +28,52 @@ #include "oops/arrayOop.hpp" #include "utilities/globalDefinitions.hpp" -// Helper for handling PartialArrayTasks. +class PartialArrayState; + +// Helper for partial array chunking tasks. // // When an array is large, we want to split it up into chunks that can be -// processed in parallel. Each task (implicitly) represents such a chunk. -// We can enqueue multiple tasks at the same time. We want to enqueue -// enough tasks to benefit from the available parallelism, while not so many -// as to substantially expand the task queues. -// -// A task directly refers to the from-space array. The from-space array's -// forwarding pointer refers to the associated to-space array, and its -// length is the actual length. The to-space array's length field is used to -// indicate processing progress. It is the starting index of the next chunk -// to process, or equals the actual length when there are no more chunks to -// be processed. +// processed in parallel. Each task (implicitly) represents such a chunk. We +// can enqueue multiple tasks at the same time. We want to enqueue enough +// tasks to benefit from the available parallelism, while not so many as to +// substantially expand the task queues. class PartialArrayTaskStepper { public: - PartialArrayTaskStepper(uint n_workers); + PartialArrayTaskStepper(uint n_workers, size_t chunk_size); struct Step { - int _index; // Array index for the step. + size_t _index; // Array index for the step. uint _ncreate; // Number of new tasks to create. }; - // Set to's length to the end of the initial chunk, which is the start of - // the first partial task if the array is large enough to need splitting. - // Returns a Step with _index being that index and _ncreate being the - // initial number of partial tasks to enqueue. - inline Step start(arrayOop from, arrayOop to, int chunk_size) const; + // Called with the length of the array to be processed. Returns a Step with + // _index being the end of the initial chunk, which the caller should + // process. This is also the starting index for the next chunk to process. + // The _ncreate is the number of tasks to enqueue to continue processing the + // array. If _ncreate is zero then _index will be length. + inline Step start(size_t length) const; + + // Atomically increment state's index by chunk_size() to claim the next + // chunk. Returns a Step with _index being the starting index of the + // claimed chunk and _ncreate being the number of additional partial tasks + // to enqueue. + inline Step next(PartialArrayState* state) const; - // Increment to's length by chunk_size to claim the next chunk. Returns a - // Step with _index being the starting index of the claimed chunk and - // _ncreate being the number of additional partial tasks to enqueue. - // precondition: chunk_size must be the same as used to start the task sequence. - inline Step next(arrayOop from, arrayOop to, int chunk_size) const; + // The size of chunks to claim for each task. + inline size_t chunk_size() const; class TestSupport; // For unit tests private: + // Size (number of elements) of a chunk to process. + size_t _chunk_size; // Limit on the number of partial array tasks to create for a given array. uint _task_limit; // Maximum number of new tasks to create when processing an existing task. uint _task_fanout; - // Split start/next into public part dealing with oops and private - // impl dealing with lengths and pointers to lengths, for unit testing. - // length is the actual length obtained from the from-space object. - // to_length_addr is the address of the to-space object's length value. - inline Step start_impl(int length, int* to_length_addr, int chunk_size) const; - inline Step next_impl(int length, int* to_length_addr, int chunk_size) const; + // For unit tests. + inline Step next_impl(size_t length, volatile size_t* index_addr) const; }; #endif // SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_HPP diff --git a/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp b/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp index aa9a02c4902..1d43578b5fe 100644 --- a/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp +++ b/src/hotspot/share/gc/shared/partialArrayTaskStepper.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,66 +25,46 @@ #ifndef SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP #define SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP +#include "gc/shared/partialArrayState.hpp" #include "gc/shared/partialArrayTaskStepper.hpp" - -#include "oops/arrayOop.hpp" #include "runtime/atomic.hpp" +#include "utilities/checkedCast.hpp" +#include "utilities/debug.hpp" -PartialArrayTaskStepper::Step -PartialArrayTaskStepper::start_impl(int length, - int* to_length_addr, - int chunk_size) const { - assert(chunk_size > 0, "precondition"); - - int end = length % chunk_size; // End of initial chunk. - // Set to's length to end of initial chunk. Partial tasks use that length - // field as the start of the next chunk to process. Must be done before - // enqueuing partial scan tasks, in case other threads steal any of those - // tasks. - // - // The value of end can be 0, either because of a 0-length array or - // because length is a multiple of the chunk size. Both of those are - // relatively rare and handled in the normal course of the iteration, so - // not worth doing anything special about here. - *to_length_addr = end; +size_t PartialArrayTaskStepper::chunk_size() const { + return _chunk_size; +} +PartialArrayTaskStepper::Step +PartialArrayTaskStepper::start(size_t length) const { + size_t end = length % _chunk_size; // End of initial chunk. // If the initial chunk is the complete array, then don't need any partial // tasks. Otherwise, start with just one partial task; see new task // calculation in next(). - Step result = { end, (length > end) ? 1u : 0u }; - return result; + return Step{ end, (length > end) ? 1u : 0u }; } PartialArrayTaskStepper::Step -PartialArrayTaskStepper::start(arrayOop from, arrayOop to, int chunk_size) const { - return start_impl(from->length(), to->length_addr(), chunk_size); -} - -PartialArrayTaskStepper::Step -PartialArrayTaskStepper::next_impl(int length, - int* to_length_addr, - int chunk_size) const { - assert(chunk_size > 0, "precondition"); - - // The start of the next task is in the length field of the to-space object. +PartialArrayTaskStepper::next_impl(size_t length, volatile size_t* index_addr) const { + // The start of the next task is in the state's index. // Atomically increment by the chunk size to claim the associated chunk. // Because we limit the number of enqueued tasks to being no more than the // number of remaining chunks to process, we can use an atomic add for the // claim, rather than a CAS loop. - int start = Atomic::fetch_then_add(to_length_addr, - chunk_size, - memory_order_relaxed); + size_t start = Atomic::fetch_then_add(index_addr, + _chunk_size, + memory_order_relaxed); - assert(start < length, "invariant: start %d, length %d", start, length); - assert(((length - start) % chunk_size) == 0, - "invariant: start %d, length %d, chunk size %d", - start, length, chunk_size); + assert(start < length, "invariant: start %zu, length %zu", start, length); + assert(((length - start) % _chunk_size) == 0, + "invariant: start %zu, length %zu, chunk size %zu", + start, length, _chunk_size); // Determine the number of new tasks to create. // Zero-based index for this partial task. The initial task isn't counted. - uint task_num = (start / chunk_size); + uint task_num = checked_cast(start / _chunk_size); // Number of tasks left to process, including this one. - uint remaining_tasks = (length - start) / chunk_size; + uint remaining_tasks = checked_cast((length - start) / _chunk_size); assert(remaining_tasks > 0, "invariant"); // Compute number of pending tasks, including this one. The maximum number // of tasks is a function of task_num (N) and _task_fanout (F). @@ -106,13 +86,12 @@ PartialArrayTaskStepper::next_impl(int length, // of tasks to add for this task. uint pending = MIN3(max_pending, remaining_tasks, _task_limit); uint ncreate = MIN2(_task_fanout, MIN2(remaining_tasks, _task_limit + 1) - pending); - Step result = { start, ncreate }; - return result; + return Step{ start, ncreate }; } PartialArrayTaskStepper::Step -PartialArrayTaskStepper::next(arrayOop from, arrayOop to, int chunk_size) const { - return next_impl(from->length(), to->length_addr(), chunk_size); +PartialArrayTaskStepper::next(PartialArrayState* state) const { + return next_impl(state->length(), state->index_addr()); } #endif // SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index 2e21ba33b0b..2ea75e1457c 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -576,6 +576,7 @@ class ObjArrayTask // Wrapper over an oop that is a partially scanned array. // Can be converted to a ScannerTask for placement in associated task queues. // Refers to the partially copied source array oop. +// Temporarily retained to support ParallelGC until it adopts PartialArrayState. class PartialArrayScanTask { oop _src; @@ -586,7 +587,9 @@ class PartialArrayScanTask { oop to_source_array() const { return _src; } }; -// Discriminated union over oop*, narrowOop*, and PartialArrayScanTask. +class PartialArrayState; + +// Discriminated union over oop*, narrowOop*, and PartialArrayState. // Uses a low tag in the associated pointer to identify the category. // Used as a task queue element type. class ScannerTask { @@ -624,9 +627,13 @@ class ScannerTask { explicit ScannerTask(narrowOop* p) : _p(encode(p, NarrowOopTag)) {} + // Temporarily retained to support ParallelGC until it adopts PartialArrayState. explicit ScannerTask(PartialArrayScanTask t) : _p(encode(t.to_source_array(), PartialArrayTag)) {} + explicit ScannerTask(PartialArrayState* state) : + _p(encode(state, PartialArrayTag)) {} + // Trivially copyable. // Predicate implementations assume OopTag == 0, others are powers of 2. @@ -639,10 +646,15 @@ class ScannerTask { return (raw_value() & NarrowOopTag) != 0; } + // Temporarily retained to support ParallelGC until it adopts PartialArrayState. bool is_partial_array_task() const { return (raw_value() & PartialArrayTag) != 0; } + bool is_partial_array_state() const { + return (raw_value() & PartialArrayTag) != 0; + } + oop* to_oop_ptr() const { return static_cast(decode(OopTag)); } @@ -651,9 +663,14 @@ class ScannerTask { return static_cast(decode(NarrowOopTag)); } + // Temporarily retained to support ParallelGC until it adopts PartialArrayState. PartialArrayScanTask to_partial_array_task() const { return PartialArrayScanTask(cast_to_oop(decode(PartialArrayTag))); } + + PartialArrayState* to_partial_array_state() const { + return static_cast(decode(PartialArrayTag)); + } }; #endif // SHARE_GC_SHARED_TASKQUEUE_HPP diff --git a/test/hotspot/gtest/gc/shared/test_partialArrayTaskStepper.cpp b/test/hotspot/gtest/gc/shared/test_partialArrayTaskStepper.cpp index fb797ba12c1..3bb3a74437c 100644 --- a/test/hotspot/gtest/gc/shared/test_partialArrayTaskStepper.cpp +++ b/test/hotspot/gtest/gc/shared/test_partialArrayTaskStepper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,50 +32,42 @@ using Stepper = PartialArrayTaskStepper; class PartialArrayTaskStepper::TestSupport : AllStatic { public: - static Step start(const Stepper* stepper, - int length, - int* to_length_addr, - uint chunk_size) { - return stepper->start_impl(length, to_length_addr, chunk_size); - } - static Step next(const Stepper* stepper, - int length, - int* to_length_addr, - uint chunk_size) { - return stepper->next_impl(length, to_length_addr, chunk_size); + size_t length, + size_t* to_length_addr) { + return stepper->next_impl(length, to_length_addr); } }; using StepperSupport = PartialArrayTaskStepper::TestSupport; -static int simulate(const Stepper* stepper, - int length, - int* to_length_addr, - uint chunk_size) { - Step init = StepperSupport::start(stepper, length, to_length_addr, chunk_size); +static uint simulate(const Stepper* stepper, + size_t length, + size_t* to_length_addr) { + Step init = stepper->start(length); + *to_length_addr = init._index; uint queue_count = init._ncreate; - int task = 0; + uint task = 0; for ( ; queue_count > 0; ++task) { --queue_count; - Step step = StepperSupport::next(stepper, length, to_length_addr, chunk_size); + Step step = StepperSupport::next(stepper, length, to_length_addr); queue_count += step._ncreate; } return task; } -static void run_test(int length, int chunk_size, uint n_workers) { - const PartialArrayTaskStepper stepper(n_workers); - int to_length; - int tasks = simulate(&stepper, length, &to_length, chunk_size); +static void run_test(size_t length, size_t chunk_size, uint n_workers) { + const PartialArrayTaskStepper stepper(n_workers, chunk_size); + size_t to_length; + uint tasks = simulate(&stepper, length, &to_length); ASSERT_EQ(length, to_length); ASSERT_EQ(tasks, length / chunk_size); } TEST(PartialArrayTaskStepperTest, doit) { - for (int chunk_size = 50; chunk_size <= 500; chunk_size += 50) { + for (size_t chunk_size = 50; chunk_size <= 500; chunk_size += 50) { for (uint n_workers = 1; n_workers <= 256; n_workers = (n_workers * 3 / 2 + 1)) { - for (int length = 0; length <= 1000000; length = (length * 2 + 1)) { + for (size_t length = 0; length <= 1000000; length = (length * 2 + 1)) { run_test(length, chunk_size, n_workers); } // Ensure we hit boundary cases for length % chunk_size == 0. From 0e7c1c1afeaba1c125b70cabe7b1b7a3193ee5c3 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Mon, 12 Aug 2024 06:26:27 +0000 Subject: [PATCH 33/84] 8338112: Test testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java fails with release build Reviewed-by: chagedorn, thartmann --- .../ir_framework/tests/TestPrivilegedMode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java index 347b2eb39fb..2122be83a0f 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java @@ -31,7 +31,7 @@ /* * @test - * @requires vm.flagless + * @requires vm.debug == true & vm.compiler2.enabled & vm.flagless * @summary Test that IR framework successfully adds test class to boot classpath in order to run in privileged mode. * @modules java.base/jdk.internal.vm.annotation * @library /test/lib / From 692f5cbdb9bd94f03e5f18ddf07d56fbb5c0d456 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Mon, 12 Aug 2024 07:32:10 +0000 Subject: [PATCH 34/84] 8338101: remove old remap assertion in map_or_reserve_memory_aligned after JDK-8338058 Reviewed-by: mdoerr, clanger --- src/hotspot/os/windows/os_windows.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 65ba13b0d9e..cb0fe95269b 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3462,8 +3462,8 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi os::attempt_reserve_memory_at(aligned_base, size, false, flag); } - assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts?", max_attempts); - assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts (size %zu, alignment %zu, file descriptor %d)", max_attempts, size, alignment, file_desc); + assert(aligned_base != nullptr, + "Did not manage to re-map after %d attempts (size %zu, alignment %zu, file descriptor %d)", max_attempts, size, alignment, file_desc); return aligned_base; } From 03204600c596214895ef86581eba9722f76d39b3 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Mon, 12 Aug 2024 07:38:43 +0000 Subject: [PATCH 35/84] 8337958: Out-of-bounds array access in secondary_super_cache Reviewed-by: vlivanov, shade --- src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 4 ++-- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 4 ++-- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 5 ++--- src/hotspot/share/oops/klass.cpp | 13 ++++++++----- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 25dfaca6dca..9dd4371cf69 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -1730,8 +1730,8 @@ void MacroAssembler::lookup_secondary_supers_table_slow_path(Register r_super_kl // The bitmap is full to bursting. // Implicit invariant: BITMAP_FULL implies (length > 0) assert(Klass::SECONDARY_SUPERS_BITMAP_FULL == ~uintx(0), ""); - cmn(r_bitmap, (u1)1); - br(EQ, L_huge); + cmpw(r_array_length, (u1)(Klass::SECONDARY_SUPERS_TABLE_SIZE - 2)); + br(GT, L_huge); // NB! Our caller has checked bits 0 and 1 in the bitmap. The // current slot (at secondary_supers[r_array_index]) has not yet diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index e0b24b7fd66..c6624cb45bb 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -3973,8 +3973,8 @@ void MacroAssembler::lookup_secondary_supers_table_slow_path(Register r_super_kl // Check if bitmap is SECONDARY_SUPERS_BITMAP_FULL assert(Klass::SECONDARY_SUPERS_BITMAP_FULL == ~uintx(0), "Adjust this code"); - addi(t0, r_bitmap, (u1)1); - beqz(t0, L_bitmap_full); + subw(t0, r_array_length, Klass::SECONDARY_SUPERS_TABLE_SIZE - 2); + bgtz(t0, L_bitmap_full); // NB! Our caller has checked bits 0 and 1 in the bitmap. The // current slot (at secondary_supers[r_array_index]) has not yet diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index c8234d6b9b8..78bcabb2000 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -4945,9 +4945,8 @@ void MacroAssembler::lookup_secondary_supers_table_slow_path(Register r_super_kl // The bitmap is full to bursting. // Implicit invariant: BITMAP_FULL implies (length > 0) - assert(Klass::SECONDARY_SUPERS_BITMAP_FULL == ~uintx(0), ""); - cmpq(r_bitmap, (int32_t)-1); // sign-extends immediate to 64-bit value - jcc(Assembler::equal, L_huge); + cmpl(r_array_length, (int32_t)Klass::SECONDARY_SUPERS_TABLE_SIZE - 2); + jcc(Assembler::greater, L_huge); // NB! Our caller has checked bits 0 and 1 in the bitmap. The // current slot (at secondary_supers[r_array_index]) has not yet diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 1fed317a860..964bb030b96 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -306,6 +306,7 @@ void Klass::set_secondary_supers(Array* secondaries, uintx bitmap) { if (UseSecondarySupersTable && secondaries != nullptr) { uintx real_bitmap = compute_secondary_supers_bitmap(secondaries); assert(bitmap == real_bitmap, "must be"); + assert(secondaries->length() >= (int)population_count(bitmap), "must be"); } #endif _bitmap = bitmap; @@ -344,11 +345,12 @@ uintx Klass::hash_secondary_supers(Array* secondaries, bool rewrite) { return uintx(1) << hash_slot; } - // For performance reasons we don't use a hashed table unless there - // are at least two empty slots in it. If there were only one empty - // slot it'd take a long time to create the table and the resulting - // search would be no faster than linear probing. - if (length > SECONDARY_SUPERS_TABLE_SIZE - 2) { + // Invariant: _secondary_supers.length >= population_count(_secondary_supers_bitmap) + + // Don't attempt to hash a table that's completely full, because in + // the case of an absent interface linear probing would not + // terminate. + if (length >= SECONDARY_SUPERS_TABLE_SIZE) { return SECONDARY_SUPERS_BITMAP_FULL; } @@ -788,6 +790,7 @@ void Klass::remove_java_mirror() { void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { assert(is_klass(), "ensure C++ vtable is restored"); assert(is_shared(), "must be set"); + assert(secondary_supers()->length() >= (int)population_count(_bitmap), "must be"); JFR_ONLY(RESTORE_ID(this);) if (log_is_enabled(Trace, cds, unshareable)) { ResourceMark rm(THREAD); From a6c0630737bbf2f2e6c64863ff9b43c50c4742b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Mon, 12 Aug 2024 10:58:05 +0000 Subject: [PATCH 36/84] 8337938: ZUtils::alloc_aligned allocates without reporting to NMT Reviewed-by: stefank, kbarrett --- src/hotspot/os/posix/gc/z/zUtils_posix.cpp | 43 ------------------- .../os/windows/gc/z/zUtils_windows.cpp | 40 ----------------- src/hotspot/share/gc/z/zStat.cpp | 4 +- src/hotspot/share/gc/z/zUtils.hpp | 4 +- src/hotspot/share/gc/z/zUtils.inline.hpp | 15 ++++++- src/hotspot/share/gc/z/zValue.inline.hpp | 6 +-- 6 files changed, 21 insertions(+), 91 deletions(-) delete mode 100644 src/hotspot/os/posix/gc/z/zUtils_posix.cpp delete mode 100644 src/hotspot/os/windows/gc/z/zUtils_windows.cpp diff --git a/src/hotspot/os/posix/gc/z/zUtils_posix.cpp b/src/hotspot/os/posix/gc/z/zUtils_posix.cpp deleted file mode 100644 index dc5af2b973a..00000000000 --- a/src/hotspot/os/posix/gc/z/zUtils_posix.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "precompiled.hpp" -#include "gc/z/zUtils.hpp" -#include "utilities/debug.hpp" -#include "utilities/globalDefinitions.hpp" - -#include - -uintptr_t ZUtils::alloc_aligned(size_t alignment, size_t size) { - void* res = nullptr; - - // Use raw posix_memalign as long as we have no wrapper for it - ALLOW_C_FUNCTION(::posix_memalign, int rc = posix_memalign(&res, alignment, size);) - if (rc != 0) { - fatal("posix_memalign() failed"); - } - - memset(res, 0, size); - - return (uintptr_t)res; -} diff --git a/src/hotspot/os/windows/gc/z/zUtils_windows.cpp b/src/hotspot/os/windows/gc/z/zUtils_windows.cpp deleted file mode 100644 index 29f7f55e2d1..00000000000 --- a/src/hotspot/os/windows/gc/z/zUtils_windows.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "precompiled.hpp" -#include "gc/z/zUtils.hpp" -#include "utilities/debug.hpp" - -#include - -uintptr_t ZUtils::alloc_aligned(size_t alignment, size_t size) { - void* const res = _aligned_malloc(size, alignment); - - if (res == nullptr) { - fatal("_aligned_malloc failed"); - } - - memset(res, 0, size); - - return (uintptr_t)res; -} diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp index 613f7b2740b..c2a7a23c04f 100644 --- a/src/hotspot/share/gc/z/zStat.cpp +++ b/src/hotspot/share/gc/z/zStat.cpp @@ -35,7 +35,7 @@ #include "gc/z/zRelocationSetSelector.inline.hpp" #include "gc/z/zStat.hpp" #include "gc/z/zTracer.inline.hpp" -#include "gc/z/zUtils.hpp" +#include "gc/z/zUtils.inline.hpp" #include "memory/metaspaceUtils.hpp" #include "memory/resourceArea.hpp" #include "runtime/atomic.hpp" @@ -364,7 +364,7 @@ void ZStatValue::initialize() { // Allocation aligned memory const size_t size = _cpu_offset * ZCPU::count(); - _base = ZUtils::alloc_aligned(ZCacheLineSize, size); + _base = ZUtils::alloc_aligned_unfreeable(ZCacheLineSize, size); } const char* ZStatValue::group() const { diff --git a/src/hotspot/share/gc/z/zUtils.hpp b/src/hotspot/share/gc/z/zUtils.hpp index f82ef06235c..59e789d5b38 100644 --- a/src/hotspot/share/gc/z/zUtils.hpp +++ b/src/hotspot/share/gc/z/zUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ class ZUtils : public AllStatic { static const char* thread_name(); // Allocation - static uintptr_t alloc_aligned(size_t alignment, size_t size); + static uintptr_t alloc_aligned_unfreeable(size_t alignment, size_t size); // Size conversion static size_t bytes_to_words(size_t size_in_words); diff --git a/src/hotspot/share/gc/z/zUtils.inline.hpp b/src/hotspot/share/gc/z/zUtils.inline.hpp index eda9fca9398..b6acf12df30 100644 --- a/src/hotspot/share/gc/z/zUtils.inline.hpp +++ b/src/hotspot/share/gc/z/zUtils.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,11 +28,24 @@ #include "gc/z/zAddress.inline.hpp" #include "oops/oop.inline.hpp" +#include "runtime/os.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +inline uintptr_t ZUtils::alloc_aligned_unfreeable(size_t alignment, size_t size) { + const size_t padded_size = size + (alignment - 1); + void* const addr = os::malloc(padded_size, mtGC); + void* const aligned_addr = align_up(addr, alignment); + + memset(aligned_addr, 0, size); + + // Since free expects pointers returned by malloc, aligned_addr cannot be + // freed since it is most likely not the same as addr after alignment. + return (uintptr_t)aligned_addr; +} + inline size_t ZUtils::bytes_to_words(size_t size_in_bytes) { assert(is_aligned(size_in_bytes, BytesPerWord), "Size not word aligned"); return size_in_bytes >> LogBytesPerWord; diff --git a/src/hotspot/share/gc/z/zValue.inline.hpp b/src/hotspot/share/gc/z/zValue.inline.hpp index b8c86cdd5c5..2367bac0f0a 100644 --- a/src/hotspot/share/gc/z/zValue.inline.hpp +++ b/src/hotspot/share/gc/z/zValue.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ #include "gc/z/zCPU.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zNUMA.hpp" -#include "gc/z/zUtils.hpp" +#include "gc/z/zUtils.inline.hpp" #include "runtime/globals.hpp" #include "utilities/align.hpp" @@ -58,7 +58,7 @@ uintptr_t ZValueStorage::alloc(size_t size) { // Allocate new block of memory const size_t block_alignment = offset; const size_t block_size = offset * S::count(); - _top = ZUtils::alloc_aligned(block_alignment, block_size); + _top = ZUtils::alloc_aligned_unfreeable(block_alignment, block_size); _end = _top + offset; // Retry allocation From 89a15f1414f89d2dd32eac791e9155fcb4207e56 Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Mon, 12 Aug 2024 12:09:22 +0000 Subject: [PATCH 37/84] 8337681: PNGImageWriter uses much more memory than necessary Reviewed-by: prr, lbourges --- .../imageio/plugins/png/PNGImageWriter.java | 22 ++- .../plugins/png/RasterReuseWriteTest.java | 182 ++++++++++++++++++ 2 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 test/jdk/javax/imageio/plugins/png/RasterReuseWriteTest.java diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java index 27707613f76..ca9ba7631ca 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java @@ -26,6 +26,7 @@ package com.sun.imageio.plugins.png; import java.awt.Rectangle; +import java.awt.image.BufferedImage; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; @@ -919,17 +920,28 @@ private void encodePass(ImageOutputStream os, int bitDepth = metadata.IHDR_bitDepth; for (int row = minY + yOffset; row < minY + height; row += ySkip) { - Rectangle rect = new Rectangle(minX, row, width, 1); - Raster ras = image.getData(rect); + Raster ras; + if (image instanceof BufferedImage bi) { + // Use the raster directly (no copy). + ras = bi.getRaster(); + } else if (image.getNumXTiles() == 1 && image.getNumYTiles() == 1 && + image.getTileWidth() == width && image.getTileHeight() == height) { + // Use the single tile directly (no copy). + ras = image.getTile(image.getMinTileX(), image.getMinTileY()); + } else { + // Make a copy of the raster data. + Rectangle rect = new Rectangle(minX, row, width, 1); + ras = image.getData(rect); + } + if (sourceBands != null) { - ras = ras.createChild(minX, row, width, 1, minX, row, - sourceBands); + ras = ras.createChild(minX, row, width, 1, minX, row, sourceBands); } ras.getPixels(minX, row, width, 1, samples); if (image.getColorModel().isAlphaPremultiplied()) { - WritableRaster wr = ras.createCompatibleWritableRaster(); + WritableRaster wr = ras.createCompatibleWritableRaster(minX, row, width, 1); wr.setPixels(wr.getMinX(), wr.getMinY(), wr.getWidth(), wr.getHeight(), samples); diff --git a/test/jdk/javax/imageio/plugins/png/RasterReuseWriteTest.java b/test/jdk/javax/imageio/plugins/png/RasterReuseWriteTest.java new file mode 100644 index 00000000000..64adaa6d196 --- /dev/null +++ b/test/jdk/javax/imageio/plugins/png/RasterReuseWriteTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8337681 + * @summary Test that raster use optimization does not cause any regressions. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; +import javax.imageio.stream.MemoryCacheImageOutputStream; + +public class RasterReuseWriteTest { + + public static void main(String[] args) throws Exception { + test(BufferedImage.TYPE_INT_RGB); + test(BufferedImage.TYPE_INT_ARGB); + test(BufferedImage.TYPE_INT_ARGB_PRE); + test(BufferedImage.TYPE_4BYTE_ABGR); + test(BufferedImage.TYPE_4BYTE_ABGR_PRE); + } + + private static void test(int type) throws Exception { + + // swaps blue and red + int bands = (type == BufferedImage.TYPE_INT_RGB ? 3 : 4); + int[] sourceBands = bands == 3 ? new int[] { 2, 1, 0 } : + new int[] { 2, 1, 0, 3 }; + + // test writing a BufferedImage without source bands + BufferedImage img1 = createImage(256, 256, type); + byte[] bytes1 = writePng(img1, null); + BufferedImage img2 = ImageIO.read(new ByteArrayInputStream(bytes1)); + compare(img1, img2, false); + + // test writing a BufferedImage with source bands + BufferedImage img3 = createImage(256, 256, type); + byte[] bytes3 = writePng(img3, sourceBands); + BufferedImage img4 = ImageIO.read(new ByteArrayInputStream(bytes3)); + compare(img3, img4, true); + + // test writing a non-BufferedImage with source bands and one tile + RenderedImage img5 = toTiledImage(img1, 256); + byte[] bytes5 = writePng(img5, sourceBands); + BufferedImage img6 = ImageIO.read(new ByteArrayInputStream(bytes5)); + compare(img5, img6, true); + + // test writing a non-BufferedImage with source bands and multiple tiles + RenderedImage img7 = toTiledImage(img1, 128); + byte[] bytes7 = writePng(img7, sourceBands); + BufferedImage img8 = ImageIO.read(new ByteArrayInputStream(bytes7)); + compare(img7, img8, true); + } + + private static BufferedImage createImage(int w, int h, int type) throws Exception { + BufferedImage img = new BufferedImage(w, h, type); + Graphics2D g2d = img.createGraphics(); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, w, h); + g2d.setColor(Color.GREEN); + g2d.drawRect(20, 20, 100, 50); + g2d.setColor(Color.RED); + g2d.drawRect(80, 10, 100, 40); + g2d.setColor(Color.BLUE); + g2d.fillRect(40, 60, 120, 30); + g2d.dispose(); + return img; + } + + private static byte[] writePng(RenderedImage img, int[] sourceBands) throws Exception { + ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next(); + ImageWriteParam param = writer.getDefaultWriteParam(); + param.setSourceBands(sourceBands); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream stream = new MemoryCacheImageOutputStream(baos); + writer.setOutput(stream); + writer.write(null, new IIOImage(img, null, null), param); + writer.dispose(); + stream.flush(); + return baos.toByteArray(); + } + + private static void compare(RenderedImage img1, RenderedImage img2, boolean blueAndRedSwapped) { + int[] pixels1 = getRgbPixels(img1); + int[] pixels2 = getRgbPixels(img2); + for (int i = 0; i < pixels1.length; i++) { + int expected; + if (blueAndRedSwapped && pixels1[i] == 0xFFFF0000) { + expected = 0xFF0000FF; // red -> blue + } else if (blueAndRedSwapped && pixels1[i] == 0xFF0000FF) { + expected = 0xFFFF0000; // blue -> red + } else { + expected = pixels1[i]; // no change + } + int actual = pixels2[i]; + if (actual != expected) { + throw new RuntimeException("Pixel " + i + ": expected " + + Integer.toHexString(expected) + ", but got " + + Integer.toHexString(actual)); + } + } + } + + private static int[] getRgbPixels(RenderedImage img) { + int w = img.getWidth(); + int h = img.getHeight(); + if (img instanceof BufferedImage bi) { + return bi.getRGB(0, 0, w, h, null, 0, w); + } else { + BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = bi.createGraphics(); + g2d.drawRenderedImage(img, new AffineTransform()); + g2d.dispose(); + return bi.getRGB(0, 0, w, h, null, 0, w); + } + } + + private static RenderedImage toTiledImage(BufferedImage img, int tileSize) throws Exception { + + // write to TIFF + ImageWriter writer = ImageIO.getImageWritersByFormatName("tiff").next(); + ImageWriteParam param = writer.getDefaultWriteParam(); + param.setTilingMode(ImageWriteParam.MODE_EXPLICIT); + param.setTiling(tileSize, tileSize, 0, 0); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageOutputStream stream = new MemoryCacheImageOutputStream(baos); + writer.setOutput(stream); + writer.write(null, new IIOImage(img, null, null), param); + writer.dispose(); + stream.flush(); + byte[] bytes = baos.toByteArray(); + + // read from TIFF + ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next(); + ImageInputStream input = ImageIO.createImageInputStream(new ByteArrayInputStream(bytes)); + reader.setInput(input); + RenderedImage ri = reader.readAsRenderedImage(0, null); + if (ri instanceof BufferedImage) { + throw new RuntimeException("Unexpected BufferedImage"); + } + int tw = ri.getTileWidth(); + int th = ri.getTileHeight(); + if (tw != tileSize || th != tileSize) { + throw new RuntimeException("Expected tile size " + tileSize + + ", but found " + tw + "x" + th); + } + return ri; + } +} From 61d1dc59535a3dc186bc1986a04efdb4e5a8fa18 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Mon, 12 Aug 2024 13:52:57 +0000 Subject: [PATCH 38/84] 8334466: Ambiguous method call with generics may cause FunctionDescriptorLookupError Reviewed-by: jlahoda --- .../com/sun/tools/javac/comp/Resolve.java | 14 ++++++++--- ...WithFunctionDescriptorLookupErrorTest.java | 25 +++++++++++++++++++ ...hWithFunctionDescriptorLookupErrorTest.out | 2 ++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.java create mode 100644 test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index c71b6d341dc..5bf1bc0ead1 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1219,9 +1219,17 @@ private boolean unrelatedInterfaces(Type t, Type s) { /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree) { - Type tDesc = types.findDescriptorType(types.capture(t)); - Type tDescNoCapture = types.findDescriptorType(t); - Type sDesc = types.findDescriptorType(s); + Type tDesc; + Type tDescNoCapture; + Type sDesc; + try { + tDesc = types.findDescriptorType(types.capture(t)); + tDescNoCapture = types.findDescriptorType(t); + sDesc = types.findDescriptorType(s); + } catch (Types.FunctionDescriptorLookupError ex) { + // don't report, a more meaningful error should be reported upstream + return false; + } final List tTypeParams = tDesc.getTypeArguments(); final List tTypeParamsNoCapture = tDescNoCapture.getTypeArguments(); final List sTypeParams = sDesc.getTypeArguments(); diff --git a/test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.java b/test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.java new file mode 100644 index 00000000000..bfdfc30609d --- /dev/null +++ b/test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.java @@ -0,0 +1,25 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8334466 + * @summary Ambiguous method call with generics may cause FunctionDescriptorLookupError + * @compile/fail/ref=CrashWithFunctionDescriptorLookupErrorTest.out -XDrawDiagnostics CrashWithFunctionDescriptorLookupErrorTest.java + */ + +import java.util.List; + +class CrashWithFunctionDescriptorLookupErrorTest { + void m() { + List list = List.of(new X()); + test(list.get(0)); + } + + void test(A a) { } + void test(B b) { } + + interface A> { T a(); } + interface B> { T b(); } + class X implements A, B { + public X a() { return null; } + public X b() { return null; } + } +} diff --git a/test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.out b/test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.out new file mode 100644 index 00000000000..06afbc8bc18 --- /dev/null +++ b/test/langtools/tools/javac/lambda/CrashWithFunctionDescriptorLookupErrorTest.out @@ -0,0 +1,2 @@ +CrashWithFunctionDescriptorLookupErrorTest.java:13:9: compiler.err.ref.ambiguous: test, kindname.method, test(CrashWithFunctionDescriptorLookupErrorTest.A), CrashWithFunctionDescriptorLookupErrorTest, kindname.method, test(CrashWithFunctionDescriptorLookupErrorTest.B), CrashWithFunctionDescriptorLookupErrorTest +1 error From a36fb368e1a3630d32908884f4abdc3382eb9aaa Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Mon, 12 Aug 2024 15:33:31 +0000 Subject: [PATCH 39/84] 8338108: Give better error message in configure if a full XCode is missing Reviewed-by: jwaters, erikj, shade --- make/autoconf/toolchain.m4 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index 57064df1ed7..12d450cc708 100644 --- a/make/autoconf/toolchain.m4 +++ b/make/autoconf/toolchain.m4 @@ -678,6 +678,9 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], test_metal=`$METAL --version 2>&1` if test $? -ne 0; then AC_MSG_RESULT([no]) + AC_MSG_NOTICE([A full XCode is required to build the JDK (not only command line tools)]) + AC_MSG_NOTICE([If you have XCode installed, you might need to reset the Xcode active developer directory]) + AC_MSG_NOTICE([using 'sudo xcode-select -r']) AC_MSG_ERROR([XCode tool 'metal' neither found in path nor with xcrun]) else AC_MSG_RESULT([yes, will be using '$METAL']) From 04b146a31f55825e2c8e3c8e42310b3b3337ae95 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Mon, 12 Aug 2024 15:43:40 +0000 Subject: [PATCH 40/84] 8337334: Test tools/javac/7142086/T7142086.java timeout with fastdebug binary Reviewed-by: vromero --- test/langtools/TEST.ROOT | 3 ++- test/langtools/tools/javac/7142086/T7142086.java | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index 11daad5244f..d816d5b096b 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -42,4 +42,5 @@ requires.extraPropDefns.vmOpts = \ -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI \ --add-exports java.base/jdk.internal.foreign=ALL-UNNAMED requires.properties= \ - vm.continuations + vm.continuations \ + vm.debug diff --git a/test/langtools/tools/javac/7142086/T7142086.java b/test/langtools/tools/javac/7142086/T7142086.java index bc8260bd486..b6521b7ffbc 100644 --- a/test/langtools/tools/javac/7142086/T7142086.java +++ b/test/langtools/tools/javac/7142086/T7142086.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,20 @@ /* * @test - * @bug 7142086 + * @bug 7142086 8337334 + * @requires vm.debug == false * @summary performance problem in Check.checkOverrideClashes(...) * @modules jdk.compiler * @run main/timeout=10 T7142086 */ +/* + * @test + * @requires vm.debug == true + * @modules jdk.compiler + * @run main/timeout=20 T7142086 + */ + import com.sun.source.util.JavacTask; import java.net.URI; import java.util.List; From f84240bca80d2ff01e198bb67931ad4725a5b334 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Mon, 12 Aug 2024 16:03:41 +0000 Subject: [PATCH 41/84] 8338011: CDS archived heap object support for 64-bit Windows Reviewed-by: stuefe, shade, ccheung --- src/hotspot/share/cds/filemap.cpp | 42 +++++++++++++++++--------- src/hotspot/share/cds/heapShared.cpp | 1 - src/hotspot/share/utilities/macros.hpp | 4 +-- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 96c826fb67e..c5a9d5cceed 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -2178,21 +2178,35 @@ bool FileMapInfo::map_heap_region_impl() { // Map the archived heap data. No need to call MemTracker::record_virtual_memory_type() // for mapped region as it is part of the reserved java heap, which is already recorded. char* addr = (char*)_mapped_heap_memregion.start(); - char* base = map_memory(_fd, _full_path, r->file_offset(), - addr, _mapped_heap_memregion.byte_size(), r->read_only(), - r->allow_exec()); - if (base == nullptr || base != addr) { - dealloc_heap_region(); - log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. " - INTPTR_FORMAT ", size = " SIZE_FORMAT " bytes", - p2i(addr), _mapped_heap_memregion.byte_size()); - return false; - } + char* base; - if (VerifySharedSpaces && !r->check_region_crc(base)) { - dealloc_heap_region(); - log_info(cds)("UseSharedSpaces: mapped heap region is corrupt"); - return false; + if (MetaspaceShared::use_windows_memory_mapping()) { + if (!read_region(MetaspaceShared::hp, addr, + align_up(_mapped_heap_memregion.byte_size(), os::vm_page_size()), + /* do_commit = */ true)) { + dealloc_heap_region(); + log_error(cds)("Failed to read archived heap region into " INTPTR_FORMAT, p2i(addr)); + return false; + } + // Checks for VerifySharedSpaces is already done inside read_region() + base = addr; + } else { + base = map_memory(_fd, _full_path, r->file_offset(), + addr, _mapped_heap_memregion.byte_size(), r->read_only(), + r->allow_exec()); + if (base == nullptr || base != addr) { + dealloc_heap_region(); + log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. " + INTPTR_FORMAT ", size = " SIZE_FORMAT " bytes", + p2i(addr), _mapped_heap_memregion.byte_size()); + return false; + } + + if (VerifySharedSpaces && !r->check_region_crc(base)) { + dealloc_heap_region(); + log_info(cds)("UseSharedSpaces: mapped heap region is corrupt"); + return false; + } } r->set_mapped_base(base); diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index ff84ddc13fc..0a0dc56c894 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -1554,7 +1554,6 @@ void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], // by any of these static fields. // At runtime, these classes are initialized before X's archived fields // are restored by HeapShared::initialize_from_archived_subgraph(). - int i; for (int i = 0; fields[i].valid(); ) { ArchivableStaticFieldInfo* info = &fields[i]; const char* klass_name = info->klass_name; diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp index 244b18ecdd4..1034dec0d9a 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -621,7 +621,7 @@ #define COMPILER_HEADER(basename) XSTR(COMPILER_HEADER_STEM(basename).hpp) #define COMPILER_HEADER_INLINE(basename) XSTR(COMPILER_HEADER_STEM(basename).inline.hpp) -#if INCLUDE_CDS && INCLUDE_G1GC && defined(_LP64) && !defined(_WINDOWS) +#if INCLUDE_CDS && INCLUDE_G1GC && defined(_LP64) #define INCLUDE_CDS_JAVA_HEAP 1 #define CDS_JAVA_HEAP_ONLY(x) x #define NOT_CDS_JAVA_HEAP(x) From 8d0831478338e9b084b2c47f46eba9faae3a5eb6 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Mon, 12 Aug 2024 17:15:39 +0000 Subject: [PATCH 42/84] 8337795: Type annotation attached to incorrect type during class reading Reviewed-by: vromero --- .../com/sun/tools/javac/jvm/ClassReader.java | 145 ++++++++---------- .../processing/model/type/BasicAnnoTests.java | 4 + 2 files changed, 65 insertions(+), 84 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index dba5fb6a197..fcc1efda8dc 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -36,9 +36,9 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.function.BiFunction; import java.util.function.IntFunction; import java.util.function.Predicate; +import java.util.stream.IntStream; import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; @@ -2461,13 +2461,8 @@ private Type addTypeAnnotations(Type type, Predicate fil .add(attribute); } - // Search the structure of the type to find the contained types at each type path - Map> attributesByType = new HashMap<>(); - new TypeAnnotationLocator(attributesByPath, attributesByType).visit(type, List.nil()); - // Rewrite the type and add the annotations - type = new TypeAnnotationTypeMapping(attributesByType).visit(type, null); - Assert.check(attributesByType.isEmpty(), "Failed to apply annotations to types"); + type = new TypeAnnotationStructuralTypeMapping(attributesByPath).visit(type, List.nil()); return type; } @@ -2495,120 +2490,102 @@ private static Predicate classExtends(int index) { } /** - * Visit all contained types, assembling a type path to represent the current location, and - * record the types at each type path that need to be annotated. + * A type mapping that rewrites the type to include type annotations. + * + *

This logic is similar to {@link Type.StructuralTypeMapping}, but also tracks the path to + * the contained types being rewritten, and so cannot easily share the existing logic. */ - private static class TypeAnnotationLocator - extends Types.DefaultTypeVisitor> { + private static final class TypeAnnotationStructuralTypeMapping + extends Types.TypeMapping> { + private final Map, - ListBuffer> attributesByPath; - private final Map> attributesByType; + ListBuffer> attributesByPath; - private TypeAnnotationLocator( + private TypeAnnotationStructuralTypeMapping( Map, ListBuffer> - attributesByPath, - Map> attributesByType) { + attributesByPath) { this.attributesByPath = attributesByPath; - this.attributesByType = attributesByType; } + @Override - public Void visitClassType(ClassType t, List path) { + public Type visitClassType(ClassType t, List path) { // As described in JVMS 4.7.20.2, type annotations on nested types are located with // 'left-to-right' steps starting on 'the outermost part of the type for which a type // annotation is admissible'. So the current path represents the outermost containing // type of the type being visited, and we add type path steps for every contained nested // type. - List enclosing = List.nil(); - for (Type curr = t; - curr != null && curr != Type.noType; + Type outer = t.getEnclosingType(); + Type outer1 = outer != Type.noType ? visit(outer, path) : outer; + for (Type curr = t.getEnclosingType(); + curr != Type.noType; curr = curr.getEnclosingType()) { - enclosing = enclosing.prepend((ClassType) curr); - } - for (ClassType te : enclosing) { - if (te.typarams_field != null) { - int i = 0; - for (Type typaram : te.typarams_field) { - visit(typaram, path.append(new TypeAnnotationPosition.TypePathEntry( - TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i++))); - } - } - visitType(te, path); path = path.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE); } - return null; + List typarams = t.getTypeArguments(); + List typarams1 = rewriteTypeParams(path, typarams); + if (outer1 != outer || typarams != typarams1) { + t = new ClassType(outer1, typarams1, t.tsym, t.getMetadata()); + } + return reannotate(t, path); } - @Override - public Void visitWildcardType( - WildcardType t, List path) { - visit(t.type, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD)); - return super.visitWildcardType(t, path); + private List rewriteTypeParams( + List path, List typarams) { + var i = IntStream.iterate(0, x -> x + 1).iterator(); + return typarams.map(typaram -> visit(typaram, + path.append(new TypeAnnotationPosition.TypePathEntry( + TypeAnnotationPosition.TypePathEntryKind.TYPE_ARGUMENT, i.nextInt())))); } @Override - public Void visitArrayType(ArrayType t, List path) { - visit(t.elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY)); - return super.visitArrayType(t, path); + public Type visitWildcardType( + WildcardType wt, List path) { + Type t = wt.type; + if (t != null) { + t = visit(t, path.append(TypeAnnotationPosition.TypePathEntry.WILDCARD)); + } + if (t != wt.type) { + wt = new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.getMetadata()); + } + return reannotate(wt, path); } @Override - public Void visitType(Type t, List path) { - ListBuffer attributes = attributesByPath.remove(path); - if (attributes != null) { - attributesByType.put(t, attributes.toList()); + public Type visitArrayType(ArrayType t, List path) { + Type elemtype = t.elemtype; + Type elemtype1 = + visit(elemtype, path.append(TypeAnnotationPosition.TypePathEntry.ARRAY)); + if (elemtype1 != elemtype) { + t = new ArrayType(elemtype1, t.tsym, t.getMetadata()); } - return null; + return reannotate(t, path); } - } - - /** A type mapping that rewrites the type to include type annotations. */ - private static class TypeAnnotationTypeMapping extends Type.StructuralTypeMapping { - private final Map> attributesByType; - - private TypeAnnotationTypeMapping( - Map> attributesByType) { - this.attributesByType = attributesByType; + @Override + public Type visitType(Type t, List path) { + return reannotate(t, path); } - private Type reannotate(T t, BiFunction f) { - // We're relying on object identify of Type instances to record where the annotations - // need to be added, so we have to retrieve the annotations for each type before - // rewriting it, and then add them after its contained types have been rewritten. - List attributes = attributesByType.remove(t); - Type mapped = f.apply(t, null); - if (attributes == null) { - return mapped; + Type reannotate(Type type, List path) { + List attributes = attributesForPath(path); + if (attributes.isEmpty()) { + return type; } // Runtime-visible and -invisible annotations are completed separately, so if the same // type has annotations from both it will get annotated twice. - TypeMetadata.Annotations existing = mapped.getMetadata(TypeMetadata.Annotations.class); + TypeMetadata.Annotations existing = type.getMetadata(TypeMetadata.Annotations.class); if (existing != null) { existing.annotationBuffer().addAll(attributes); - return mapped; + return type; } - return mapped.annotatedType(attributes); + return type.annotatedType(attributes); } - @Override - public Type visitClassType(ClassType t, Void unused) { - return reannotate(t, super::visitClassType); - } - - @Override - public Type visitWildcardType(WildcardType t, Void unused) { - return reannotate(t, super::visitWildcardType); - } - - @Override - public Type visitArrayType(ArrayType t, Void unused) { - return reannotate(t, super::visitArrayType); - } - - @Override - public Type visitType(Type t, Void unused) { - return reannotate(t, (x, u) -> x); + List attributesForPath( + List path) { + ListBuffer attributes = attributesByPath.remove(path); + return attributes != null ? attributes.toList() : List.nil(); } } diff --git a/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java b/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java index d45edc8e3d6..acd91eac8c7 100644 --- a/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java +++ b/test/langtools/tools/javac/processing/model/type/BasicAnnoTests.java @@ -717,4 +717,8 @@ private class GenericNested { GenericNested(@TA(120) GenericInner120 GenericInner120.this) {} } } + + @Test(posn=1, annoType=TA.class, expect="130") + @Test(posn=23, annoType=TA.class, expect="131") + public Map<@TA(130) String, @TA(131) String> f130; } From 99edb4a45d6a4a871dec9c07b41b3ab66b89a4b6 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 12 Aug 2024 17:20:20 +0000 Subject: [PATCH 43/84] 8337702: Use new ForwardExceptionNode to call StubRoutines::forward_exception_entry() Reviewed-by: thartmann --- src/hotspot/cpu/aarch64/aarch64.ad | 13 ++++++++ src/hotspot/cpu/arm/arm.ad | 14 +++++++++ src/hotspot/cpu/ppc/ppc.ad | 15 +++++++++ src/hotspot/cpu/riscv/riscv.ad | 16 ++++++++++ src/hotspot/cpu/s390/s390.ad | 14 +++++++++ src/hotspot/cpu/x86/x86_32.ad | 12 ++++++++ src/hotspot/cpu/x86/x86_64.ad | 12 ++++++++ src/hotspot/share/adlc/formssel.cpp | 34 ++++++++++++--------- src/hotspot/share/opto/callnode.hpp | 11 +++++++ src/hotspot/share/opto/classes.hpp | 1 + src/hotspot/share/opto/domgraph.cpp | 1 + src/hotspot/share/opto/gcm.cpp | 5 ++- src/hotspot/share/opto/generateOptoStub.cpp | 14 ++++----- src/hotspot/share/opto/matcher.cpp | 15 ++++++++- src/hotspot/share/runtime/vmStructs.cpp | 1 + 15 files changed, 153 insertions(+), 25 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index d8db75961d8..66a24a61f29 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -16184,6 +16184,19 @@ instruct TailjmpInd(iRegPNoSpNoRfp jump_target, iRegP_R0 ex_oop) ins_pipe(pipe_class_call); %} +// Forward exception. +instruct ForwardExceptionjmp() +%{ + match(ForwardException); + ins_cost(CALL_COST); + + format %{ "b forward_exception_stub" %} + ins_encode %{ + __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + %} + ins_pipe(pipe_class_call); +%} + // Create exception oop: created by stack-crawling runtime code. // Created exception is now available to this handler, and is setup // just prior to jumping to this handler. No code emitted. diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 638c48ad5aa..2c7de0a58a2 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -8953,6 +8953,20 @@ instruct tailjmpInd(IPRegP jump_target, RExceptionRegP ex_oop) %{ ins_pipe(tail_call); %} +// Forward exception. +instruct ForwardExceptionjmp() +%{ + match(ForwardException); + ins_cost(CALL_COST); + + format %{ "b forward_exception_stub" %} + ins_encode %{ + // OK to trash Rtemp, because Rtemp is used by stub + __ jump(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type, Rtemp); + %} + ins_pipe(tail_call); +%} + // Create exception oop: created by stack-crawling runtime code. // Created exception is now available to this handler, and is setup // just prior to jumping to this handler. No code emitted. diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 38485da9581..b34d3ef1501 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -14534,6 +14534,21 @@ instruct tailjmpInd(iRegPdstNoScratch jump_target, rarg1RegP ex_oop) %{ ins_pipe(pipe_class_call); %} +// Forward exception. +instruct ForwardExceptionjmp() +%{ + match(ForwardException); + ins_cost(CALL_COST); + + format %{ "Jmp forward_exception_stub" %} + ins_encode %{ + __ set_inst_mark(); + __ b64_patchable(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ clear_inst_mark(); + %} + ins_pipe(pipe_class_call); +%} + // Create exception oop: created by stack-crawling runtime code. // Created exception is now available to this handler, and is setup // just prior to jumping to this handler. No code emitted. diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 1e26c2bf142..d3e2b0549e9 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -10617,6 +10617,22 @@ instruct TailjmpInd(iRegPNoSpNoFp jump_target, iRegP_R10 ex_oop) ins_pipe(pipe_class_call); %} +// Forward exception. +instruct ForwardExceptionjmp() +%{ + match(ForwardException); + + ins_cost(BRANCH_COST); + + format %{ "j forward_exception_stub\t#@ForwardException" %} + + ins_encode %{ + __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + %} + + ins_pipe(pipe_class_call); +%} + // Create exception oop: created by stack-crawling runtime code. // Created exception is now available to this handler, and is setup // just prior to jumping to this handler. No code emitted. diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index e3dcfdb8759..4de1a4e7b7f 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -9517,6 +9517,20 @@ instruct tailjmpInd(iRegP jump_target, rarg1RegP ex_oop) %{ ins_pipe(pipe_class_dummy); %} +// Forward exception. +instruct ForwardExceptionjmp() %{ + match(ForwardException); + ins_cost(CALL_COST); + format %{ "Jmp forward_exception_stub" %} + ins_encode %{ + __ set_inst_mark(); + __ load_const_optimized(Z_R1_scratch, (address)StubRoutines::forward_exception_entry()); + __ z_br(Z_R1_scratch); + __ clear_inst_mark(); + %} + ins_pipe(pipe_class_dummy); +%} + // Create exception oop: created by stack-crawling runtime code. // Created exception is now available to this handler, and is setup // just prior to jumping to this handler. No code emitted. diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 49a3cad37df..7aa4f6a29a1 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -13583,6 +13583,18 @@ instruct tailjmpInd(eRegP_no_EBP jump_target, eAXRegP ex_oop) %{ ins_pipe( pipe_jmp ); %} +// Forward exception. +instruct ForwardExceptionjmp() +%{ + match(ForwardException); + + format %{ "JMP forward_exception_stub" %} + ins_encode %{ + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry()), noreg); + %} + ins_pipe(pipe_jmp); +%} + // Create exception oop: created by stack-crawling runtime code. // Created exception is now available to this handler, and is setup // just prior to jumping to this handler. No code emitted. diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 1490cfa60b3..3bc4cac2f06 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -12592,6 +12592,18 @@ instruct tailjmpInd(no_rbp_RegP jump_target, rax_RegP ex_oop) ins_pipe(pipe_jmp); %} +// Forward exception. +instruct ForwardExceptionjmp() +%{ + match(ForwardException); + + format %{ "jmp forward_exception_stub" %} + ins_encode %{ + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry()), noreg); + %} + ins_pipe(pipe_jmp); +%} + // Create exception oop: created by stack-crawling runtime code. // Created exception is now available to this handler, and is setup // just prior to jumping to this handler. No code emitted. diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index be97547f8ce..e7df38ff221 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -210,15 +210,16 @@ bool InstructForm::is_pinned(FormDict &globals) { if ( ! _matrule) return false; int index = 0; - if (_matrule->find_type("Goto", index)) return true; - if (_matrule->find_type("If", index)) return true; - if (_matrule->find_type("CountedLoopEnd",index)) return true; - if (_matrule->find_type("Return", index)) return true; - if (_matrule->find_type("Rethrow", index)) return true; - if (_matrule->find_type("TailCall", index)) return true; - if (_matrule->find_type("TailJump", index)) return true; - if (_matrule->find_type("Halt", index)) return true; - if (_matrule->find_type("Jump", index)) return true; + if (_matrule->find_type("Goto", index)) return true; + if (_matrule->find_type("If", index)) return true; + if (_matrule->find_type("CountedLoopEnd", index)) return true; + if (_matrule->find_type("Return", index)) return true; + if (_matrule->find_type("Rethrow", index)) return true; + if (_matrule->find_type("TailCall", index)) return true; + if (_matrule->find_type("TailJump", index)) return true; + if (_matrule->find_type("ForwardException", index)) return true; + if (_matrule->find_type("Halt", index)) return true; + if (_matrule->find_type("Jump", index)) return true; return is_parm(globals); } @@ -228,12 +229,13 @@ bool InstructForm::is_projection(FormDict &globals) { if ( ! _matrule) return false; int index = 0; - if (_matrule->find_type("Goto", index)) return true; - if (_matrule->find_type("Return", index)) return true; - if (_matrule->find_type("Rethrow", index)) return true; - if (_matrule->find_type("TailCall",index)) return true; - if (_matrule->find_type("TailJump",index)) return true; - if (_matrule->find_type("Halt", index)) return true; + if (_matrule->find_type("Goto", index)) return true; + if (_matrule->find_type("Return", index)) return true; + if (_matrule->find_type("Rethrow", index)) return true; + if (_matrule->find_type("TailCall", index)) return true; + if (_matrule->find_type("TailJump", index)) return true; + if (_matrule->find_type("ForwardException", index)) return true; + if (_matrule->find_type("Halt", index)) return true; return false; } @@ -376,6 +378,7 @@ bool InstructForm::is_ideal_return() const { if (_matrule->find_type("Rethrow",index)) return true; if (_matrule->find_type("TailCall",index)) return true; if (_matrule->find_type("TailJump",index)) return true; + if (_matrule->find_type("ForwardException", index)) return true; return false; } @@ -894,6 +897,7 @@ uint InstructForm::oper_input_base(FormDict &globals) { strcmp(_matrule->_opType,"Rethrow" )==0 || strcmp(_matrule->_opType,"TailCall" )==0 || strcmp(_matrule->_opType,"TailJump" )==0 || + strcmp(_matrule->_opType,"ForwardException")==0 || strcmp(_matrule->_opType,"SafePoint" )==0 || strcmp(_matrule->_opType,"Halt" )==0 ) return AdlcVMDeps::Parms; // Skip the machine-state edges diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 120bb112ec5..2d3835b71ad 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -152,6 +152,17 @@ class RethrowNode : public Node { }; +//------------------------------ForwardExceptionNode--------------------------- +// Pop stack frame and jump to StubRoutines::forward_exception_entry() +class ForwardExceptionNode : public ReturnNode { +public: + ForwardExceptionNode(Node* cntrl, Node* i_o, Node* memory, Node* frameptr, Node* retadr) + : ReturnNode(TypeFunc::Parms, cntrl, i_o, memory, frameptr, retadr) { + } + + virtual int Opcode() const; +}; + //------------------------------TailCallNode----------------------------------- // Pop stack frame and jump indirect class TailCallNode : public ReturnNode { diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index dc613776873..8bee6279446 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -184,6 +184,7 @@ macro(FastLock) macro(FastUnlock) macro(FmaD) macro(FmaF) +macro(ForwardException) macro(Goto) macro(Halt) macro(CountPositives) diff --git a/src/hotspot/share/opto/domgraph.cpp b/src/hotspot/share/opto/domgraph.cpp index 363005d1181..84f83ef131b 100644 --- a/src/hotspot/share/opto/domgraph.cpp +++ b/src/hotspot/share/opto/domgraph.cpp @@ -239,6 +239,7 @@ uint Block_Stack::most_frequent_successor( Block *b ) { break; case Op_TailCall: case Op_TailJump: + case Op_ForwardException: case Op_Return: case Op_Halt: case Op_Rethrow: diff --git a/src/hotspot/share/opto/gcm.cpp b/src/hotspot/share/opto/gcm.cpp index 23ae8cbcb6b..3880bea07d7 100644 --- a/src/hotspot/share/opto/gcm.cpp +++ b/src/hotspot/share/opto/gcm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2031,6 +2031,7 @@ float Block::succ_prob(uint i) { case Op_TailCall: case Op_TailJump: + case Op_ForwardException: case Op_Return: case Op_Halt: case Op_Rethrow: @@ -2084,6 +2085,7 @@ int Block::num_fall_throughs() { case Op_NeverBranch: case Op_TailCall: case Op_TailJump: + case Op_ForwardException: case Op_Return: case Op_Halt: case Op_Rethrow: @@ -2129,6 +2131,7 @@ bool Block::succ_fall_through(uint i) { case Op_NeverBranch: case Op_TailCall: case Op_TailJump: + case Op_ForwardException: case Op_Return: case Op_Halt: case Op_Rethrow: diff --git a/src/hotspot/share/opto/generateOptoStub.cpp b/src/hotspot/share/opto/generateOptoStub.cpp index 9bd7d42a3f9..e22f484c179 100644 --- a/src/hotspot/share/opto/generateOptoStub.cpp +++ b/src/hotspot/share/opto/generateOptoStub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,13 +255,11 @@ void GraphKit::gen_stub(address C_function, Node* if_not_null = _gvn.transform( new IfTrueNode(iff) ); assert (StubRoutines::forward_exception_entry() != nullptr, "must be generated before"); - Node *exc_target = makecon(TypeRawPtr::make( StubRoutines::forward_exception_entry() )); - Node *to_exc = new TailCallNode(if_not_null, - i_o(), - exit_memory, - frameptr(), - returnadr(), - exc_target, null()); + Node *to_exc = new ForwardExceptionNode(if_not_null, + i_o(), + exit_memory, + frameptr(), + returnadr()); root()->add_req(_gvn.transform(to_exc)); // bind to root to keep live C->init_start(start); diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 4e2306602e6..bf773d43d3d 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -804,6 +804,10 @@ void Matcher::Fixup_Save_On_Entry( ) { if (ret_edge_cnt > TypeFunc::Parms) ret_rms[TypeFunc::Parms+0] = _return_value_mask; + // Input RegMask array shared by all ForwardExceptions + uint forw_exc_edge_cnt = TypeFunc::Parms; + RegMask* forw_exc_rms = init_input_masks( forw_exc_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); + // Input RegMask array shared by all Rethrows. uint reth_edge_cnt = TypeFunc::Parms+1; RegMask *reth_rms = init_input_masks( reth_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); @@ -863,6 +867,7 @@ void Matcher::Fixup_Save_On_Entry( ) { case Op_Rethrow : exit->_in_rms = reth_rms; break; case Op_TailCall : exit->_in_rms = tail_call_rms; break; case Op_TailJump : exit->_in_rms = tail_jump_rms; break; + case Op_ForwardException: exit->_in_rms = forw_exc_rms; break; case Op_Halt : exit->_in_rms = halt_rms; break; default : ShouldNotReachHere(); } @@ -882,6 +887,7 @@ void Matcher::Fixup_Save_On_Entry( ) { reth_rms [ reth_edge_cnt] = mreg2regmask[i]; tail_call_rms[tail_call_edge_cnt] = mreg2regmask[i]; tail_jump_rms[tail_jump_edge_cnt] = mreg2regmask[i]; + forw_exc_rms [ forw_exc_edge_cnt] = mreg2regmask[i]; // Halts need the SOE registers, but only in the stack as debug info. // A just-prior uncommon-trap or deoptimization will use the SOE regs. halt_rms [ halt_edge_cnt] = *idealreg2spillmask[_register_save_type[i]]; @@ -899,6 +905,7 @@ void Matcher::Fixup_Save_On_Entry( ) { reth_rms [ reth_edge_cnt].Insert(OptoReg::Name(i+1)); tail_call_rms[tail_call_edge_cnt].Insert(OptoReg::Name(i+1)); tail_jump_rms[tail_jump_edge_cnt].Insert(OptoReg::Name(i+1)); + forw_exc_rms [ forw_exc_edge_cnt].Insert(OptoReg::Name(i+1)); halt_rms [ halt_edge_cnt].Insert(OptoReg::Name(i+1)); mproj = new MachProjNode( start, proj_cnt, ret_rms[ret_edge_cnt], Op_RegD ); proj_cnt += 2; // Skip 2 for doubles @@ -911,6 +918,7 @@ void Matcher::Fixup_Save_On_Entry( ) { reth_rms [ reth_edge_cnt] = RegMask::Empty; tail_call_rms[tail_call_edge_cnt] = RegMask::Empty; tail_jump_rms[tail_jump_edge_cnt] = RegMask::Empty; + forw_exc_rms [ forw_exc_edge_cnt] = RegMask::Empty; halt_rms [ halt_edge_cnt] = RegMask::Empty; mproj = C->top(); } @@ -925,6 +933,7 @@ void Matcher::Fixup_Save_On_Entry( ) { reth_rms [ reth_edge_cnt].Insert(OptoReg::Name(i+1)); tail_call_rms[tail_call_edge_cnt].Insert(OptoReg::Name(i+1)); tail_jump_rms[tail_jump_edge_cnt].Insert(OptoReg::Name(i+1)); + forw_exc_rms [ forw_exc_edge_cnt].Insert(OptoReg::Name(i+1)); halt_rms [ halt_edge_cnt].Insert(OptoReg::Name(i+1)); mproj = new MachProjNode( start, proj_cnt, ret_rms[ret_edge_cnt], Op_RegL ); proj_cnt += 2; // Skip 2 for longs @@ -937,6 +946,7 @@ void Matcher::Fixup_Save_On_Entry( ) { reth_rms [ reth_edge_cnt] = RegMask::Empty; tail_call_rms[tail_call_edge_cnt] = RegMask::Empty; tail_jump_rms[tail_jump_edge_cnt] = RegMask::Empty; + forw_exc_rms [ forw_exc_edge_cnt] = RegMask::Empty; halt_rms [ halt_edge_cnt] = RegMask::Empty; mproj = C->top(); } else { @@ -948,11 +958,13 @@ void Matcher::Fixup_Save_On_Entry( ) { reth_edge_cnt ++; tail_call_edge_cnt ++; tail_jump_edge_cnt ++; + forw_exc_edge_cnt++; halt_edge_cnt ++; // Add a use of the SOE register to all exit paths - for( uint j=1; j < root->req(); j++ ) + for (uint j=1; j < root->req(); j++) { root->in(j)->add_req(mproj); + } } // End of if a save-on-entry register } // End of for all machine registers } @@ -1070,6 +1082,7 @@ static void match_alias_type(Compile* C, Node* n, Node* m) { case Op_Halt: case Op_TailCall: case Op_TailJump: + case Op_ForwardException: nidx = Compile::AliasIdxBot; nat = TypePtr::BOTTOM; break; diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 4b6381bd05e..27dc10d2adb 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1422,6 +1422,7 @@ declare_c2_type(RethrowNode, Node) \ declare_c2_type(TailCallNode, ReturnNode) \ declare_c2_type(TailJumpNode, ReturnNode) \ + declare_c2_type(ForwardExceptionNode, ReturnNode) \ declare_c2_type(SafePointNode, MultiNode) \ declare_c2_type(CallNode, SafePointNode) \ declare_c2_type(CallJavaNode, CallNode) \ From 2ca136a7adb6defaea3b7a69d30e6c36bda66e6a Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Mon, 12 Aug 2024 17:26:51 +0000 Subject: [PATCH 44/84] 8337815: Relax G1EvacStats atomic operations Reviewed-by: kbarrett, tschatzl, shade --- src/hotspot/share/gc/g1/g1EvacStats.inline.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp b/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp index 4b4c6e104b7..d4cae1f9836 100644 --- a/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp +++ b/src/hotspot/share/gc/g1/g1EvacStats.inline.hpp @@ -30,25 +30,25 @@ #include "runtime/atomic.hpp" inline void G1EvacStats::add_direct_allocated(size_t value) { - Atomic::add(&_direct_allocated, value); + Atomic::add(&_direct_allocated, value, memory_order_relaxed); } inline void G1EvacStats::add_num_plab_filled(size_t value) { - Atomic::add(&_num_plab_filled, value); + Atomic::add(&_num_plab_filled, value, memory_order_relaxed); } inline void G1EvacStats::add_num_direct_allocated(size_t value) { - Atomic::add(&_num_direct_allocated, value); + Atomic::add(&_num_direct_allocated, value, memory_order_relaxed); } inline void G1EvacStats::add_region_end_waste(size_t value) { - Atomic::add(&_region_end_waste, value); - Atomic::inc(&_regions_filled); + Atomic::add(&_region_end_waste, value, memory_order_relaxed); + Atomic::inc(&_regions_filled, memory_order_relaxed); } inline void G1EvacStats::add_failure_used_and_waste(size_t used, size_t waste) { - Atomic::add(&_failure_used, used); - Atomic::add(&_failure_waste, waste); + Atomic::add(&_failure_used, used, memory_order_relaxed); + Atomic::add(&_failure_waste, waste, memory_order_relaxed); } #endif // SHARE_GC_G1_G1EVACSTATS_INLINE_HPP From 41e31d6b0ae00d70b6fb20c89318fde2bc605edb Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 12 Aug 2024 17:56:46 +0000 Subject: [PATCH 45/84] 8337622: IllegalArgumentException in java.lang.reflect.Field.get Reviewed-by: dholmes, shade --- src/hotspot/share/classfile/javaClasses.cpp | 7 --- src/hotspot/share/classfile/javaClasses.hpp | 1 + .../reflect/ComponentTypeFieldTest.java | 50 +++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/reflect/ComponentTypeFieldTest.java diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index ab9460e2b9b..8a6c8a8ce0b 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -1452,19 +1452,12 @@ void java_lang_Class::compute_offsets() { InstanceKlass* k = vmClasses::Class_klass(); CLASS_FIELDS_DO(FIELD_COMPUTE_OFFSET); - - // Init lock is a C union with component_mirror. Only instanceKlass mirrors have - // init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops - // GC treats them the same. - _init_lock_offset = _component_mirror_offset; - CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } #if INCLUDE_CDS void java_lang_Class::serialize_offsets(SerializeClosure* f) { f->do_bool(&_offsets_computed); - f->do_u4((u4*)&_init_lock_offset); CLASS_FIELDS_DO(FIELD_SERIALIZE_OFFSET); diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 57914e189b7..eb3c5e29fdb 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -209,6 +209,7 @@ class java_lang_String : AllStatic { macro(java_lang_Class, static_oop_field_count, int_signature, false) \ macro(java_lang_Class, protection_domain, object_signature, false) \ macro(java_lang_Class, source_file, object_signature, false) \ + macro(java_lang_Class, init_lock, object_signature, false) class java_lang_Class : AllStatic { friend class VMStructs; diff --git a/test/hotspot/jtreg/runtime/reflect/ComponentTypeFieldTest.java b/test/hotspot/jtreg/runtime/reflect/ComponentTypeFieldTest.java new file mode 100644 index 00000000000..6296a7f970e --- /dev/null +++ b/test/hotspot/jtreg/runtime/reflect/ComponentTypeFieldTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8337622 + * @summary (reflect) java.lang.Class componentType field not found. + * @library /test/lib + * @modules java.base/java.lang:open + * @run main ComponentTypeFieldTest + */ + +import java.lang.reflect.Field; +import static jdk.test.lib.Asserts.*; + +public class ComponentTypeFieldTest { + + public static void main(String[] args) throws Exception { + Field f = Class.class.getDeclaredField("componentType"); + f.setAccessible(true); + Object val = f.get(Runnable.class); + assertTrue(val == null); + System.out.println("val is " + val); + + Object arrayVal = f.get(Integer[].class); + System.out.println("val is " + arrayVal); + String arrayValString = arrayVal.toString(); + assertTrue(arrayValString.equals("class java.lang.Integer")); + } +} From b93b74e3ebd220e94fb5e33d2ebc62181db97bb0 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Mon, 12 Aug 2024 19:28:46 +0000 Subject: [PATCH 46/84] 8338060: jdk/internal/util/ReferencedKeyTest should be more robust Reviewed-by: never --- .../jdk/internal/util/ReferencedKeyTest.java | 130 ++++++++++-------- 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/test/jdk/jdk/internal/util/ReferencedKeyTest.java b/test/jdk/jdk/internal/util/ReferencedKeyTest.java index 75690fa6e25..c68908a8d5a 100644 --- a/test/jdk/jdk/internal/util/ReferencedKeyTest.java +++ b/test/jdk/jdk/internal/util/ReferencedKeyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8285932 8310913 + * @bug 8285932 8310913 8336390 8338060 * @summary Test features provided by the ReferencedKeyMap/ReferencedKeySet classes. * @modules java.base/jdk.internal.util * @compile --patch-module java.base=${test.src} ReferencedKeyTest.java @@ -36,14 +36,27 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BooleanSupplier; +import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.IntStream; public class ReferencedKeyTest { - static long BASE_KEY = 10_000_000L; + private static String BASE_KEY = "BASEKEY-"; + + // Return a String (identity object) that can be a key in WeakHashMap. + private static String genKey(int i) { + return BASE_KEY + i; + } + + // Return a String of the letter 'a' plus the integer (0..0xffff) + private static String genValue(int i) { + return String.valueOf((char) ('a' + i)); + } public static void main(String[] args) { mapTest(false, HashMap::new); @@ -63,73 +76,77 @@ static void assertTrue(boolean test, String message) { } } - static void mapTest(boolean isSoft, Supplier, String>> supplier) { - Map map = ReferencedKeyMap.create(isSoft, supplier); - populate(map); + static void mapTest(boolean isSoft, Supplier, String>> supplier) { + Map map = ReferencedKeyMap.create(isSoft, supplier); + var strongKeys = populate(map); // Retain references to the keys + methods(map); + Reference.reachabilityFence(strongKeys); + + strongKeys = null; // drop strong key references if (!isSoft) { if (!collect(() -> map.isEmpty())) { throw new RuntimeException("WeakReference map not collecting!"); } } - populate(map); - methods(map); } - static void setTest(boolean isSoft, Supplier, ReferenceKey>> supplier) { - ReferencedKeySet set = ReferencedKeySet.create(isSoft, supplier); - populate(set); + static void setTest(boolean isSoft, Supplier, ReferenceKey>> supplier) { + ReferencedKeySet set = ReferencedKeySet.create(isSoft, supplier); + var strongKeys = populate(set); // Retain references to the keys + methods(set); + Reference.reachabilityFence(strongKeys); + + strongKeys = null; // drop strong key references if (!isSoft) { if (!collect(() -> set.isEmpty())) { throw new RuntimeException("WeakReference set not collecting!"); } } - populate(set); - methods(set); } - static void methods(Map map) { + static void methods(Map map) { assertTrue(map.size() == 26, "missing key"); - assertTrue(map.containsKey(BASE_KEY + 'a' -'a'), "missing key"); - assertTrue(map.get(BASE_KEY + 'b' -'a').equals("b"), "wrong key"); + assertTrue(map.containsKey(genKey('a' -'a')), "missing key"); + assertTrue(map.get(genKey('b' -'a')).equals("b"), "wrong key"); assertTrue(map.containsValue("c"), "missing value"); - map.remove(BASE_KEY + 'd' -'a'); - assertTrue(map.get(BASE_KEY + 'd' -'a') == null, "not removed"); - map.putAll(Map.of(1L, "A", 2L, "B")); - assertTrue(map.get(2L).equals("B"), "collection not added"); - assertTrue(map.containsKey(1L), "key missing"); + map.remove(genKey('d' -'a')); + assertTrue(map.get(genKey('d' -'a')) == null, "not removed"); + map.putAll(Map.of(genKey(1), "A", genKey(2), "B")); + assertTrue(map.get(genKey(2)).equals("B"), "collection not added"); + assertTrue(map.containsKey(genKey(1)), "key missing"); assertTrue(map.containsValue("A"), "key missing"); - assertTrue(map.entrySet().contains(Map.entry(1L, "A")), "key missing"); - map.putIfAbsent(3L, "C"); - assertTrue(map.get(3L).equals("C"), "key missing"); - map.putIfAbsent(2L, "D"); - assertTrue(map.get(2L).equals("B"), "key replaced"); - map.remove(3L); - assertTrue(map.get(3L) == null, "key not removed"); - map.replace(2L, "D"); - assertTrue(map.get(2L).equals("D"), "key not replaced"); - map.replace(2L, "B", "E"); - assertTrue(map.get(2L).equals("D"), "key replaced"); + assertTrue(map.entrySet().contains(Map.entry(genKey(1), "A")), "key missing"); + map.putIfAbsent(genKey(3), "C"); + assertTrue(map.get(genKey(3)).equals("C"), "key missing"); + map.putIfAbsent(genKey(2), "D"); + assertTrue(map.get(genKey(2)).equals("B"), "key replaced"); + map.remove(genKey(3)); + assertTrue(map.get(genKey(3)) == null, "key not removed"); + map.replace(genKey(2), "D"); + assertTrue(map.get(genKey(2)).equals("D"), "key not replaced"); + map.replace(genKey(2), "B", "E"); + assertTrue(map.get(genKey(2)).equals("D"), "key replaced"); } - static void methods(ReferencedKeySet set) { + static void methods(ReferencedKeySet set) { assertTrue(set.size() == 26, "missing key"); - assertTrue(set.contains(BASE_KEY + 3), "missing key"); - set.remove(BASE_KEY + 3); - assertTrue(!set.contains(BASE_KEY + 3), "not removed"); - Long element1 = set.get(BASE_KEY + 2); - Long element2 = set.get(BASE_KEY + 3); - Long element3 = set.get(BASE_KEY + 4); - Long intern1 = set.intern(BASE_KEY + 2); - Long intern2 = set.intern(BASE_KEY + 3); - Long intern3 = set.intern(BASE_KEY + 4, e -> e); + assertTrue(set.contains(genKey(3)), "missing key"); + set.remove(genKey(3)); + assertTrue(!set.contains(genKey(3)), "not removed"); + String element1 = set.get(genKey(2)); + String element2 = set.get(genKey(3)); + String element3 = set.get(genKey(4)); + String intern1 = set.intern(genKey(2)); + String intern2 = set.intern(genKey(3)); + String intern3 = set.intern(genKey(4), e -> e); assertTrue(element1 != null, "missing key"); assertTrue(element2 == null, "not removed"); assertTrue(element1 == intern1, "intern failed"); // must be same object assertTrue(intern2 != null, "intern failed"); assertTrue(element3 == intern3, "intern failed"); - Long value1 = Long.valueOf(BASE_KEY + 999); - Long value2 = Long.valueOf(BASE_KEY + 999); + String value1 = genKey(999); + String value2 = genKey(999); assertTrue(set.add(value1), "key not added"); assertTrue(!set.add(value1), "key added after second attempt"); assertTrue(!set.add(value2), "key should not have been added"); @@ -164,18 +181,23 @@ static boolean collect(BooleanSupplier booleanSupplier) { return booleanSupplier.getAsBoolean(); } - static void populate(Map map) { - for (int i = 0; i < 26; i++) { - Long key = BASE_KEY + i; - String value = String.valueOf((char) ('a' + i)); - map.put(key, value); + static List populate(Map map) { + var keyRefs = genStrings(0, 26, ReferencedKeyTest::genKey); + var valueRefs = genStrings(0, 26, ReferencedKeyTest::genValue); + for (int i = 0; i < keyRefs.size(); i++) { + map.put(keyRefs.get(i), valueRefs.get(i)); } + return keyRefs; } - static void populate(Set set) { - for (int i = 0; i < 26; i++) { - Long value = BASE_KEY + i; - set.add(value); - } + static List populate(Set set) { + var keyRefs = genStrings(0, 26, ReferencedKeyTest::genKey); + set.addAll(keyRefs); + return keyRefs; + } + + // Generate a List of consecutive strings using a function int -> String + static List genStrings(int min, int maxExclusive, Function genString) { + return IntStream.range(min, maxExclusive).mapToObj(i -> genString.apply(i)).toList(); } } From 4417c276e484c1fe137ed7f4a7c28709d0c99af2 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Mon, 12 Aug 2024 19:43:36 +0000 Subject: [PATCH 47/84] 8330535: Update nsk/jdb tests to use driver instead of othervm Reviewed-by: cjplummer --- .../caught_exception002/caught_exception002.java | 10 +++------- .../nsk/jdb/classes/classes001/classes001.java | 10 +++------- .../jdb/classpath/classpath001/classpath001.java | 10 +++------- .../vmTestbase/nsk/jdb/clear/clear002/clear002.java | 10 +++------- .../vmTestbase/nsk/jdb/clear/clear003/clear003.java | 10 +++------- .../vmTestbase/nsk/jdb/clear/clear004/clear004.java | 8 ++------ .../vmTestbase/nsk/jdb/down/down002/down002.java | 10 +++------- .../vmTestbase/nsk/jdb/dump/dump002/dump002.java | 10 +++------- .../vmTestbase/nsk/jdb/eval/eval001/eval001.java | 10 +++------- .../nsk/jdb/exclude/exclude001/exclude001.java | 10 +++------- .../nsk/jdb/fields/fields001/fields001.java | 10 +++------- .../nsk/jdb/hidden_class/hc001/hc001.java | 10 +++------- .../nsk/jdb/ignore/ignore001/ignore001.java | 10 +++------- .../jdb/interrupt/interrupt001/interrupt001.java | 10 +++------- .../vmTestbase/nsk/jdb/kill/kill001/kill001.java | 10 +++------- .../vmTestbase/nsk/jdb/kill/kill002/kill002.java | 10 +++------- .../vmTestbase/nsk/jdb/klass/class001/class001.java | 10 +++------- .../vmTestbase/nsk/jdb/list/list002/list002.java | 10 +++------- .../vmTestbase/nsk/jdb/list/list003/list003.java | 11 ++++------- .../nsk/jdb/locals/locals002/locals002.java | 10 +++------- .../nsk/jdb/methods/methods002/methods002.java | 10 +++------- .../nsk/jdb/monitor/monitor001/monitor001.java | 10 +++------- .../nsk/jdb/monitor/monitor002/monitor002.java | 10 +++------- .../vmTestbase/nsk/jdb/next/next001/next001.java | 10 +++------- .../jdb/options/connect/connect001/connect001.java | 10 +++------- .../jdb/options/connect/connect002/connect002.java | 10 +++------- .../jdb/options/connect/connect003/connect003.java | 10 +++------- .../jdb/options/connect/connect004/connect004.java | 10 +++------- .../jdb/options/connect/connect005/connect005.java | 13 ++++--------- .../listconnectors001/listconnectors001.java | 10 +++------- .../jtreg/vmTestbase/nsk/jdb/pop/pop001/pop001.java | 10 +++------- .../pop_exception001/pop_exception001.java | 10 +++------- .../vmTestbase/nsk/jdb/print/print002/print002.java | 10 +++------- .../vmTestbase/nsk/jdb/read/read001/read001.java | 10 +++------- .../nsk/jdb/redefine/redefine001/redefine001.java | 10 +++------- .../nsk/jdb/reenter/reenter001/reenter001.java | 10 +++------- .../nsk/jdb/regression/b4689395/b4689395.java | 10 +++------- .../nsk/jdb/repeat/repeat001/repeat001.java | 10 +++------- .../nsk/jdb/resume/resume002/resume002.java | 10 +++------- .../jtreg/vmTestbase/nsk/jdb/run/run002/run002.java | 10 +++------- .../jtreg/vmTestbase/nsk/jdb/set/set001/set001.java | 10 +++------- .../jtreg/vmTestbase/nsk/jdb/set/set002/set002.java | 10 +++------- .../vmTestbase/nsk/jdb/step/step002/step002.java | 10 +++------- .../nsk/jdb/step_up/step_up001/step_up001.java | 10 +++------- .../nsk/jdb/stop_at/stop_at002/stop_at002.java | 8 ++------ .../nsk/jdb/stop_at/stop_at003/stop_at003.java | 10 +++------- .../nsk/jdb/stop_in/stop_in002/stop_in002.java | 10 +++------- .../nsk/jdb/suspend/suspend001/suspend001.java | 10 +++------- .../nsk/jdb/thread/thread002/thread002.java | 10 +++------- .../threadgroup/threadgroup002/threadgroup002.java | 10 +++------- .../threadgroups002/threadgroups002.java | 10 +++------- .../nsk/jdb/threads/threads002/threads002.java | 10 +++------- .../nsk/jdb/threads/threads003/threads003.java | 10 +++------- .../vmTestbase/nsk/jdb/trace/trace001/trace001.java | 10 +++------- .../uncaught_exception002.java | 10 +++------- .../jdb/unmonitor/unmonitor001/unmonitor001.java | 10 +++------- .../nsk/jdb/untrace/untrace001/untrace001.java | 10 +++------- .../nsk/jdb/unwatch/unwatch001/unwatch001.java | 10 +++------- .../nsk/jdb/unwatch/unwatch002/unwatch002.java | 10 +++------- .../jtreg/vmTestbase/nsk/jdb/up/up002/up002.java | 10 +++------- .../jtreg/vmTestbase/nsk/jdb/use/use001/use001.java | 10 +++------- .../vmTestbase/nsk/jdb/watch/watch001/watch001.java | 10 +++------- .../vmTestbase/nsk/jdb/watch/watch002/watch002.java | 10 +++------- .../vmTestbase/nsk/jdb/where/where004/where004.java | 10 +++------- .../vmTestbase/nsk/jdb/where/where005/where005.java | 10 +++------- .../vmTestbase/nsk/jdb/where/where006/where006.java | 10 +++------- .../nsk/jdb/wherei/wherei001/wherei001.java | 10 +++------- .../jtreg/vmTestbase/nsk/share/jdb/JdbTest.java | 11 +++++------ .../jtreg/vmTestbase/nsk/share/jdb/Launcher.java | 6 ++++-- 69 files changed, 210 insertions(+), 477 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/caught_exception/caught_exception002/caught_exception002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/caught_exception/caught_exception002/caught_exception002.java index 4eef7900d42..04ace5ba49c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/caught_exception/caught_exception002/caught_exception002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/caught_exception/caught_exception002/caught_exception002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.caught_exception.caught_exception002.caught_exception002a - * @run main/othervm + * @run driver * nsk.jdb.caught_exception.caught_exception002.caught_exception002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -69,14 +69,10 @@ public class caught_exception002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new caught_exception002().runTest(argv, out); + new caught_exception002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.caught_exception.caught_exception002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/classes/classes001/classes001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/classes/classes001/classes001.java index 40a5ebaa939..8543c7c6f1e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/classes/classes001/classes001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/classes/classes001/classes001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.classes.classes001.classes001a - * @run main/othervm + * @run driver * nsk.jdb.classes.classes001.classes001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -60,14 +60,10 @@ public class classes001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new classes001().runTest(argv, out); + new classes001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.classes.classes001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/classpath/classpath001/classpath001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/classpath/classpath001/classpath001.java index 0eea9a92ab2..25a86fe64cb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/classpath/classpath001/classpath001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/classpath/classpath001/classpath001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.classpath.classpath001.classpath001a - * @run main/othervm + * @run driver * nsk.jdb.classpath.classpath001.classpath001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -59,14 +59,10 @@ public class classpath001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new classpath001().runTest(argv, out); + new classpath001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.classpath.classpath001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear002/clear002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear002/clear002.java index 7869a1340a7..cca80dad465 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear002/clear002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear002/clear002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.clear.clear002.clear002a - * @run main/othervm + * @run driver * nsk.jdb.clear.clear002.clear002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -61,14 +61,10 @@ public class clear002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new clear002().runTest(argv, out); + new clear002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.clear.clear002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear003/clear003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear003/clear003.java index cbbc851f29a..003b1f36edd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear003/clear003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear003/clear003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -39,7 +39,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.clear.clear003.clear003a - * @run main/othervm + * @run driver * nsk.jdb.clear.clear003.clear003 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -62,14 +62,10 @@ public class clear003 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new clear003().runTest(argv, out); + new clear003().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.clear.clear003"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear004/clear004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear004/clear004.java index c0ec8d20370..5dfd33430e3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear004/clear004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/clear/clear004/clear004.java @@ -40,7 +40,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.clear.clear004.clear004a - * @run main/othervm + * @run driver * nsk.jdb.clear.clear004.clear004 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -63,14 +63,10 @@ public class clear004 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new clear004().runTest(argv, out); + new clear004().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.clear.clear004"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/down/down002/down002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/down/down002/down002.java index 29a40d9471d..99f4254891d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/down/down002/down002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/down/down002/down002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.down.down002.down002a - * @run main/othervm + * @run driver * nsk.jdb.down.down002.down002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -66,14 +66,10 @@ public class down002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new down002().runTest(argv, out); + new down002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.down.down002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/dump/dump002/dump002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/dump/dump002/dump002.java index 3e3b5b9b858..66a26e69f77 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/dump/dump002/dump002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/dump/dump002/dump002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.dump.dump002.dump002a - * @run main/othervm + * @run driver * nsk.jdb.dump.dump002.dump002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -70,15 +70,11 @@ public class dump002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; compoundPromptIdent = COMPOUND_PROMPT_IDENT; - return new dump002().runTest(argv, out); + new dump002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.dump.dump002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/eval/eval001/eval001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/eval/eval001/eval001.java index 98848ced90b..fc4fb14dd2d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/eval/eval001/eval001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/eval/eval001/eval001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @clean nsk.jdb.eval.eval001.eval001a * @compile -g:lines,source,vars eval001a.java * - * @run main/othervm + * @run driver * nsk.jdb.eval.eval001.eval001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -75,14 +75,10 @@ public class eval001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new eval001().runTest(argv, out); + new eval001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.eval.eval001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/exclude/exclude001/exclude001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/exclude/exclude001/exclude001.java index cee8ca44d58..c7805cc6c95 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/exclude/exclude001/exclude001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/exclude/exclude001/exclude001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.exclude.exclude001.exclude001a - * @run main/othervm/timeout=600 + * @run driver/timeout=600 * nsk.jdb.exclude.exclude001.exclude001 * -arch=${os.family}-${os.simpleArch} * -waittime=10 @@ -82,14 +82,10 @@ public class exclude001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new exclude001().runTest(argv, out); + new exclude001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.exclude.exclude001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/fields/fields001/fields001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/fields/fields001/fields001.java index b5e2ccb58e5..c1cbba3232a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/fields/fields001/fields001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/fields/fields001/fields001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.fields.fields001.fields001a - * @run main/othervm + * @run driver * nsk.jdb.fields.fields001.fields001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -64,14 +64,10 @@ public class fields001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new fields001().runTest(argv, out); + new fields001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.fields.fields001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/hidden_class/hc001/hc001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/hidden_class/hc001/hc001.java index 5040eef9cef..a7c74e28aae 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/hidden_class/hc001/hc001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/hidden_class/hc001/hc001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * jdk.jdwp.agent * @build nsk.jdb.hidden_class.hc001.hc001a * - * @run main/othervm + * @run driver * nsk.jdb.hidden_class.hc001.hc001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -60,13 +60,9 @@ public class hc001 extends JdbTest { static final int MAX_SLEEP_CNT = 3; public static void main(String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; // needed for JdbTest.runTest firstBreak = MAIN_METHOD_NAME; // needed for JdbTest.runTest - return new hc001().runTest(argv, out); + new hc001().runTest(argv); } static boolean checkPattern(String[] arr, String pattern) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/ignore/ignore001/ignore001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/ignore/ignore001/ignore001.java index 6eb8c91e1eb..48d256d22fc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/ignore/ignore001/ignore001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/ignore/ignore001/ignore001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.ignore.ignore001.ignore001a - * @run main/othervm + * @run driver * nsk.jdb.ignore.ignore001.ignore001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -63,14 +63,10 @@ public class ignore001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new ignore001().runTest(argv, out); + new ignore001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.ignore.ignore001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java index 73f251b71e9..51bbdf6757a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/interrupt/interrupt001/interrupt001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.interrupt.interrupt001.interrupt001a - * @run main/othervm + * @run driver * nsk.jdb.interrupt.interrupt001.interrupt001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -73,13 +73,9 @@ public class interrupt001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; - return new interrupt001().runTest(argv, out); + new interrupt001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.interrupt.interrupt001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001.java index b770aafc510..a96498954b6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill001/kill001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.kill.kill001.kill001a - * @run main/othervm + * @run driver * nsk.jdb.kill.kill001.kill001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -74,13 +74,9 @@ public class kill001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; - return new kill001().runTest(argv, out); + new kill001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.kill.kill001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill002/kill002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill002/kill002.java index 230dcdf12ba..ed5306346dc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill002/kill002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/kill/kill002/kill002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.kill.kill002.kill002a - * @run main/othervm + * @run driver * nsk.jdb.kill.kill002.kill002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -66,13 +66,9 @@ public class kill002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; - return new kill002().runTest(argv, out); + new kill002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.kill.kill002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/klass/class001/class001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/klass/class001/class001.java index 4c548348dc3..ee37e393f70 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/klass/class001/class001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/klass/class001/class001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.klass.class001.class001a - * @run main/othervm + * @run driver * nsk.jdb.klass.class001.class001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -63,14 +63,10 @@ public class class001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new class001().runTest(argv, out); + new class001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.klass.class001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list002/list002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list002/list002.java index 4180ea3bb45..38282a425ec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list002/list002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list002/list002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ * /test/lib * @build nsk.jdb.list.list002.list002a * @run driver jdk.test.lib.FileInstaller list002a.java src/nsk/jdb/list/list002/list002a.java - * @run main/othervm + * @run driver * nsk.jdb.list.list002.list002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -68,14 +68,10 @@ public class list002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new list002().runTest(argv, out); + new list002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.list.list002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list003/list003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list003/list003.java index d06bf38bd85..e7d773486ee 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list003/list003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/list/list003/list003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.list.list003.list003a - * @run main/othervm + * @run driver * nsk.jdb.list.list003.list003 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -47,6 +47,7 @@ * -jdb.option="-J-Duser.language=en -J-Duser.country=US" * -java.options="${test.vm.opts} ${test.java.opts}" * -workdir=. + * -jdb.option="-sourcepath ${test.src}/../../../.." * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" */ @@ -98,13 +99,9 @@ protected List parseListOutput(String[] lines) { } public static void main(String[] args) { - System.exit(run(args, System.out) + JCK_STATUS_BASE); - } - - public static int run(String[] args, PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; - return new list003().runTest(args, out); + new list003().runTest(args); } @Override diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/locals/locals002/locals002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/locals/locals002/locals002.java index 793cdc04608..09a97ff83a5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/locals/locals002/locals002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/locals/locals002/locals002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @clean nsk.jdb.locals.locals002.locals002a * @compile -g:lines,source,vars locals002a.java * - * @run main/othervm + * @run driver * nsk.jdb.locals.locals002.locals002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -75,15 +75,11 @@ public class locals002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; compoundPromptIdent = COMPOUND_PROMPT_IDENT; - return new locals002().runTest(argv, out); + new locals002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.locals.locals002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/methods/methods002/methods002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/methods/methods002/methods002.java index 2bacbab101b..ef480d52c03 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/methods/methods002/methods002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/methods/methods002/methods002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.methods.methods002.methods002a - * @run main/othervm + * @run driver * nsk.jdb.methods.methods002.methods002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -73,14 +73,10 @@ public class methods002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new methods002().runTest(argv, out); + new methods002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.methods.methods002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor001/monitor001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor001/monitor001.java index 1fd1f8c328b..94cac5ca787 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor001/monitor001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor001/monitor001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.monitor.monitor001.monitor001a - * @run main/othervm + * @run driver * nsk.jdb.monitor.monitor001.monitor001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -69,14 +69,10 @@ public class monitor001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new monitor001().runTest(argv, out); + new monitor001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.monitor.monitor001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java index 53c856128ce..790eb746916 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.monitor.monitor002.monitor002a - * @run main/othervm + * @run driver * nsk.jdb.monitor.monitor002.monitor002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -65,14 +65,10 @@ public class monitor002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new monitor002().runTest(argv, out); + new monitor002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.monitor.monitor002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/next/next001/next001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/next/next001/next001.java index 206199f0bb3..3d0c810b5c4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/next/next001/next001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/next/next001/next001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.next.next001.next001a - * @run main/othervm + * @run driver * nsk.jdb.next.next001.next001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -69,14 +69,10 @@ public class next001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new next001().runTest(argv, out); + new next001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.next.next001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect001/connect001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect001/connect001.java index a78f3a96db4..85cdbb27997 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect001/connect001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect001/connect001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.options.connect.connect001.connect001a - * @run main/othervm + * @run driver * nsk.jdb.options.connect.connect001.connect001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -71,14 +71,10 @@ public class connect001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new connect001().runTest(argv, out); + new connect001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.options.connect.connect001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect002/connect002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect002/connect002.java index 78bcf2fb973..a3219de0cc4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect002/connect002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect002/connect002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.options.connect.connect002.connect002a - * @run main/othervm + * @run driver * nsk.jdb.options.connect.connect002.connect002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -71,14 +71,10 @@ public class connect002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new connect002().runTest(argv, out); + new connect002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.options.connect.connect002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect003/connect003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect003/connect003.java index 701f611d2ff..465e3c9deb2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect003/connect003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect003/connect003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.options.connect.connect003.connect003a - * @run main/othervm + * @run driver * nsk.jdb.options.connect.connect003.connect003 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -71,14 +71,10 @@ public class connect003 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new connect003().runTest(argv, out); + new connect003().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.options.connect.connect003"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect004/connect004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect004/connect004.java index adaa58627dd..075e9c30268 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect004/connect004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect004/connect004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.options.connect.connect004.connect004a - * @run main/othervm + * @run driver * nsk.jdb.options.connect.connect004.connect004 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -71,14 +71,10 @@ public class connect004 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new connect004().runTest(argv, out); + new connect004().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.options.connect.connect004"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect005/connect005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect005/connect005.java index 8a670392466..7bd44a5927c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect005/connect005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/connect/connect005/connect005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.options.connect.connect005.connect005a - * @run main/othervm + * @run driver * nsk.jdb.options.connect.connect005.connect005 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -70,15 +70,10 @@ public class connect005 extends JdbTest { - public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { - debuggeeClass = DEBUGGEE_CLASS; + public static void main (String argv[]) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new connect005().runTest(argv, out); + new connect005().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.options.connect.connect005"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/listconnectors/listconnectors001/listconnectors001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/listconnectors/listconnectors001/listconnectors001.java index d814df91cc6..b4961be11ee 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/listconnectors/listconnectors001/listconnectors001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/options/listconnectors/listconnectors001/listconnectors001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm + * @run driver * nsk.jdb.options.listconnectors.listconnectors001.listconnectors001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -75,14 +75,10 @@ public class listconnectors001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new listconnectors001().runTest(argv, out); + new listconnectors001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.options.connect"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop/pop001/pop001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop/pop001/pop001.java index e449a5771f2..c508538fa1e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop/pop001/pop001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop/pop001/pop001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.pop.pop001.pop001a - * @run main/othervm + * @run driver * nsk.jdb.pop.pop001.pop001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -70,14 +70,10 @@ public class pop001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new pop001().runTest(argv, out); + new pop001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.pop.pop001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001.java index f70a5ffb960..49921cd26cc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.pop_exception.pop_exception001.pop_exception001a - * @run main/othervm + * @run driver * nsk.jdb.pop_exception.pop_exception001.pop_exception001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -63,14 +63,10 @@ public class pop_exception001 extends JdbTest { static final String LAST_BREAK = DEBUGGEE_CLASS + ".lastBreak"; public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new pop_exception001().runTest(argv, out); + new pop_exception001().runTest(argv); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/print/print002/print002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/print/print002/print002.java index e339a0a321b..1993c1f4d95 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/print/print002/print002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/print/print002/print002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @clean nsk.jdb.print.print002.print002a * @compile -g:lines,source,vars print002a.java * - * @run main/othervm + * @run driver * nsk.jdb.print.print002.print002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -75,14 +75,10 @@ public class print002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new print002().runTest(argv, out); + new print002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.print.print002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/read/read001/read001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/read/read001/read001.java index b5ca64334d7..60c80139a65 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/read/read001/read001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/read/read001/read001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @clean nsk.jdb.read.read001.read001a * @compile -g:lines,source,vars read001a.java * - * @run main/othervm + * @run driver * nsk.jdb.read.read001.read001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -76,14 +76,10 @@ public class read001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new read001().runTest(argv, out); + new read001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.read.read001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/redefine/redefine001/redefine001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/redefine/redefine001/redefine001.java index 80ff33889a4..d3988ac443c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/redefine/redefine001/redefine001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/redefine/redefine001/redefine001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * -cp ${test.class.path} * ${test.src}/newclass_g/RedefinedClass.java * - * @run main/othervm + * @run driver * nsk.jdb.redefine.redefine001.redefine001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -80,14 +80,10 @@ public class redefine001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new redefine001().runTest(argv, out); + new redefine001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.redefine.redefine001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/reenter/reenter001/reenter001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/reenter/reenter001/reenter001.java index ebc063942c6..4013d85ab75 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/reenter/reenter001/reenter001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/reenter/reenter001/reenter001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.reenter.reenter001.reenter001a - * @run main/othervm + * @run driver * nsk.jdb.reenter.reenter001.reenter001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -69,14 +69,10 @@ public class reenter001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new reenter001().runTest(argv, out); + new reenter001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.reenter.reenter001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/regression/b4689395/b4689395.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/regression/b4689395/b4689395.java index 82d8235fee7..2cb3cc0eccf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/regression/b4689395/b4689395.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/regression/b4689395/b4689395.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ * -cp ${test.class.path} * ${test.src}/newclass/b4689395a.java * - * @run main/othervm + * @run driver * nsk.jdb.regression.b4689395.b4689395 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -131,13 +131,9 @@ public class b4689395 extends JdbTest { private String classFile; public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; - return new b4689395().runTest(argv, out); + new b4689395().runTest(argv); } public b4689395() { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/repeat/repeat001/repeat001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/repeat/repeat001/repeat001.java index e0489db2829..67ce5ea4e74 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/repeat/repeat001/repeat001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/repeat/repeat001/repeat001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.repeat.repeat001.repeat001a - * @run main/othervm + * @run driver * nsk.jdb.repeat.repeat001.repeat001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -68,13 +68,9 @@ public class repeat001 extends JdbTest { static final String FIRST_BREAK = DEBUGGEE_CLASS + ".main"; public static void main(String[] args) { - System.exit(run(args, System.out) + JCK_STATUS_BASE); - } - - public static int run(String[] args, PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; - return new repeat001().runTest(args, out); + new repeat001().runTest(args); } protected static boolean isPrompt(String line) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/resume/resume002/resume002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/resume/resume002/resume002.java index ab4df2625fe..9607413036c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/resume/resume002/resume002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/resume/resume002/resume002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.resume.resume002.resume002a - * @run main/othervm + * @run driver * nsk.jdb.resume.resume002.resume002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -73,14 +73,10 @@ public class resume002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new resume002().runTest(argv, out); + new resume002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.resume.resume002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/run/run002/run002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/run/run002/run002.java index da837ab0f8b..9b23ac4de25 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/run/run002/run002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/run/run002/run002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.run.run002.run002a - * @run main/othervm + * @run driver * nsk.jdb.run.run002.run002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -67,14 +67,10 @@ public class run002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new run002().runTest(argv, out); + new run002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.run.run002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set001/set001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set001/set001.java index d00362b228c..7b97f47b529 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set001/set001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set001/set001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ * @clean nsk.jdb.set.set001.set001a * @compile -g:lines,source,vars set001a.java * - * @run main/othervm + * @run driver * nsk.jdb.set.set001.set001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -76,14 +76,10 @@ public class set001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new set001().runTest(argv, out); + new set001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.set.set001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set002/set002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set002/set002.java index dca4e554afa..91d84821040 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set002/set002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/set/set002/set002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ * @clean nsk.jdb.set.set002.set002a * @compile -g:lines,source,vars set002a.java * - * @run main/othervm + * @run driver * nsk.jdb.set.set002.set002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -76,15 +76,11 @@ public class set002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new set002().runTest(argv, out); + new set002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.set.set002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/step/step002/step002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/step/step002/step002.java index 4df163ca1a9..c9cc342783e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/step/step002/step002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/step/step002/step002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @clean nsk.jdb.step.step002.step002a * @compile -g:lines,source,vars step002a.java * - * @run main/othervm + * @run driver * nsk.jdb.step.step002.step002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -79,14 +79,10 @@ public class step002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new step002().runTest(argv, out); + new step002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.step.step002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/step_up/step_up001/step_up001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/step_up/step_up001/step_up001.java index 590a476dbbe..d4c60f937fa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/step_up/step_up001/step_up001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/step_up/step_up001/step_up001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.step_up.step_up001.step_up001a - * @run main/othervm + * @run driver * nsk.jdb.step_up.step_up001.step_up001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -68,14 +68,10 @@ public class step_up001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new step_up001().runTest(argv, out); + new step_up001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.step_up.step_up001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java index 9dae8c17cfc..30cb6ed2c68 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at002/stop_at002.java @@ -37,7 +37,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.stop_at.stop_at002.stop_at002a - * @run main/othervm + * @run driver * nsk.jdb.stop_at.stop_at002.stop_at002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -67,14 +67,10 @@ public class stop_at002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new stop_at002().runTest(argv, out); + new stop_at002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.stop_at.stop_at002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at003/stop_at003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at003/stop_at003.java index ecd66ca7c95..06eacea58b9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at003/stop_at003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_at/stop_at003/stop_at003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.stop_at.stop_at003.stop_at003a - * @run main/othervm + * @run driver * nsk.jdb.stop_at.stop_at003.stop_at003 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -79,14 +79,10 @@ public class stop_at003 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new stop_at003().runTest(argv, out); + new stop_at003().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.stop_at.stop_at003"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_in/stop_in002/stop_in002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_in/stop_in002/stop_in002.java index e4c2058fd97..710f05c078c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_in/stop_in002/stop_in002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/stop_in/stop_in002/stop_in002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.stop_in.stop_in002.stop_in002a - * @run main/othervm + * @run driver * nsk.jdb.stop_in.stop_in002.stop_in002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -80,14 +80,10 @@ public class stop_in002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new stop_in002().runTest(argv, out); + new stop_in002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.stop_in.stop_in002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/suspend/suspend001/suspend001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/suspend/suspend001/suspend001.java index 18e5c27d31c..20c9778f251 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/suspend/suspend001/suspend001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/suspend/suspend001/suspend001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.suspend.suspend001.suspend001a - * @run main/othervm + * @run driver * nsk.jdb.suspend.suspend001.suspend001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -69,14 +69,10 @@ public class suspend001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new suspend001().runTest(argv, out); + new suspend001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.suspend.suspend001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/thread/thread002/thread002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/thread/thread002/thread002.java index 487ac49e66e..c8b55b0beee 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/thread/thread002/thread002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/thread/thread002/thread002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.thread.thread002.thread002a - * @run main/othervm + * @run driver * nsk.jdb.thread.thread002.thread002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -66,14 +66,10 @@ public class thread002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new thread002().runTest(argv, out); + new thread002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.thread.thread002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java index 72bbf358474..8ff58b11bec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.threadgroup.threadgroup002.threadgroup002a - * @run main/othervm + * @run driver * nsk.jdb.threadgroup.threadgroup002.threadgroup002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -69,14 +69,10 @@ public class threadgroup002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new threadgroup002().runTest(argv, out); + new threadgroup002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.threadgroup.threadgroup002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroups/threadgroups002/threadgroups002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroups/threadgroups002/threadgroups002.java index 67ee29006b4..56f4dceda9e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroups/threadgroups002/threadgroups002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroups/threadgroups002/threadgroups002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.threadgroups.threadgroups002.threadgroups002a - * @run main/othervm + * @run driver * nsk.jdb.threadgroups.threadgroups002.threadgroups002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -64,14 +64,10 @@ public class threadgroups002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new threadgroups002().runTest(argv, out); + new threadgroups002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.threadgroups.threadgroups002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads002/threads002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads002/threads002.java index e9afd794d81..fdc52ad7a2a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads002/threads002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads002/threads002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.threads.threads002.threads002a - * @run main/othervm + * @run driver * nsk.jdb.threads.threads002.threads002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -65,14 +65,10 @@ public class threads002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new threads002().runTest(argv, out); + new threads002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.threads.threads002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads003/threads003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads003/threads003.java index 4332eb69cf9..f290cc71bb5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads003/threads003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threads/threads003/threads003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.threads.threads003.threads003a - * @run main/othervm + * @run driver * nsk.jdb.threads.threads003.threads003 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -65,14 +65,10 @@ public class threads003 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new threads003().runTest(argv, out); + new threads003().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.threads.threads003"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/trace/trace001/trace001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/trace/trace001/trace001.java index 0e289f93aee..492d5b438c8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/trace/trace001/trace001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/trace/trace001/trace001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.trace.trace001.trace001a - * @run main/othervm + * @run driver * nsk.jdb.trace.trace001.trace001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -71,14 +71,10 @@ public class trace001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new trace001().runTest(argv, out); + new trace001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.trace.trace001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/uncaught_exception/uncaught_exception002/uncaught_exception002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/uncaught_exception/uncaught_exception002/uncaught_exception002.java index dd1d0748c0f..32f7750cdb5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/uncaught_exception/uncaught_exception002/uncaught_exception002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/uncaught_exception/uncaught_exception002/uncaught_exception002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ * @clean nsk.jdb.uncaught_exception.uncaught_exception002.uncaught_exception002a * @compile -g:lines,source,vars uncaught_exception002a.java * - * @run main/othervm + * @run driver * nsk.jdb.uncaught_exception.uncaught_exception002.uncaught_exception002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -75,14 +75,10 @@ public class uncaught_exception002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new uncaught_exception002(true).runTest(argv, out); + new uncaught_exception002(true).runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.uncaught_exception.uncaught_exception002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java index 7d98824be73..195b2427ae5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ * @clean nsk.jdb.unmonitor.unmonitor001.unmonitor001a * @compile -g:lines,source,vars unmonitor001a.java * - * @run main/othervm + * @run driver * nsk.jdb.unmonitor.unmonitor001.unmonitor001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -79,14 +79,10 @@ public class unmonitor001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new unmonitor001().runTest(argv, out); + new unmonitor001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.unmonitor.unmonitor001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/untrace/untrace001/untrace001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/untrace/untrace001/untrace001.java index daad477dbb4..0891e5b931c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/untrace/untrace001/untrace001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/untrace/untrace001/untrace001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.untrace.untrace001.untrace001a - * @run main/othervm + * @run driver * nsk.jdb.untrace.untrace001.untrace001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -77,14 +77,10 @@ public class untrace001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new untrace001().runTest(argv, out); + new untrace001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.untrace.untrace001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001.java index b8c71645edb..aff9890e58d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.unwatch.unwatch001.unwatch001a - * @run main/othervm + * @run driver * nsk.jdb.unwatch.unwatch001.unwatch001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -73,14 +73,10 @@ public class unwatch001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new unwatch001().runTest(argv, out); + new unwatch001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.unwatch.unwatch001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002.java index e32cc0b8e5d..1078e2b3da3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.unwatch.unwatch002.unwatch002a - * @run main/othervm + * @run driver * nsk.jdb.unwatch.unwatch002.unwatch002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -74,14 +74,10 @@ public class unwatch002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new unwatch002().runTest(argv, out); + new unwatch002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.unwatch.unwatch002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/up/up002/up002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/up/up002/up002.java index 5b2cb393df4..78c01074abb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/up/up002/up002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/up/up002/up002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.up.up002.up002a - * @run main/othervm + * @run driver * nsk.jdb.up.up002.up002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -66,14 +66,10 @@ public class up002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new up002().runTest(argv, out); + new up002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.up.up002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/use/use001/use001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/use/use001/use001.java index 1454b39b2bf..81ad1dd48ac 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/use/use001/use001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/use/use001/use001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.use.use001.use001a - * @run main/othervm + * @run driver * nsk.jdb.use.use001.use001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -67,14 +67,10 @@ public class use001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new use001().runTest(argv, out); + new use001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.use.use001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001.java index 8d434fcfc74..dfc154d1b41 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.watch.watch001.watch001a - * @run main/othervm + * @run driver * nsk.jdb.watch.watch001.watch001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -71,15 +71,11 @@ public class watch001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; compoundPromptIdent = COMPOUND_PROMPT_IDENT; - return new watch001().runTest(argv, out); + new watch001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.watch.watch001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002.java index cb0535117d9..84c80a59ebf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.watch.watch002.watch002a - * @run main/othervm + * @run driver * nsk.jdb.watch.watch002.watch002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -71,15 +71,11 @@ public class watch002 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; compoundPromptIdent = COMPOUND_PROMPT_IDENT; - return new watch002().runTest(argv, out); + new watch002().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.watch.watch002"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where004/where004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where004/where004.java index e4cbf50e62f..9002c35e16e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where004/where004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where004/where004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.where.where004.where004a - * @run main/othervm + * @run driver * nsk.jdb.where.where004.where004 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -64,14 +64,10 @@ public class where004 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new where004().runTest(argv, out); + new where004().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.where.where004"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where005/where005.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where005/where005.java index b949916aae7..2fded987272 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where005/where005.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where005/where005.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.where.where005.where005a - * @run main/othervm + * @run driver * nsk.jdb.where.where005.where005 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -65,14 +65,10 @@ public class where005 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new where005(true).runTest(argv, out); + new where005(true).runTest(argv); } public where005 (boolean debuggeeShouldFail) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where006/where006.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where006/where006.java index bf7622c48b3..11dc185238f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where006/where006.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/where/where006/where006.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.where.where006.where006a - * @run main/othervm + * @run driver * nsk.jdb.where.where006.where006 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -65,14 +65,10 @@ public class where006 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new where006().runTest(argv, out); + new where006().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.where.where006"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/wherei/wherei001/wherei001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/wherei/wherei001/wherei001.java index 431206b5551..e4d75620f0b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/wherei/wherei001/wherei001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/wherei/wherei001/wherei001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * @library /vmTestbase * /test/lib * @build nsk.jdb.wherei.wherei001.wherei001a - * @run main/othervm + * @run driver * nsk.jdb.wherei.wherei001.wherei001 * -arch=${os.family}-${os.simpleArch} * -waittime=5 @@ -60,14 +60,10 @@ public class wherei001 extends JdbTest { public static void main (String argv[]) { - System.exit(run(argv, System.out) + JCK_STATUS_BASE); - } - - public static int run(String argv[], PrintStream out) { debuggeeClass = DEBUGGEE_CLASS; firstBreak = FIRST_BREAK; lastBreak = LAST_BREAK; - return new wherei001().runTest(argv, out); + new wherei001().runTest(argv); } static final String PACKAGE_NAME = "nsk.jdb.wherei.wherei001"; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/JdbTest.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/JdbTest.java index 349216f4329..aa7ad833b53 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/JdbTest.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/JdbTest.java @@ -125,14 +125,15 @@ protected void initJdb() { protected void afterJdbExit() { } - protected int runTest(String argv[], PrintStream out) { + protected void runTest(String argv[]) { + PrintStream out = System.out; try { argumentHandler = new JdbArgumentHandler(argv); log = new Log(out, argumentHandler); if (shouldPass()) { log.println("TEST PASSED"); - return PASSED; + return; } try { @@ -226,16 +227,14 @@ protected int runTest(String argv[], PrintStream out) { if (!success) { log.complain("TEST FAILED"); - return FAILED; + throw new RuntimeException("TEST FAILED"); } } catch (Throwable t) { out.println("Caught unexpected exception while starting the test: " + t); t.printStackTrace(out); - out.println("TEST FAILED"); - return FAILED; + throw new RuntimeException("TEST FAILED", t); } out.println("TEST PASSED"); - return PASSED; } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java index 35df95b2d6f..d4437413495 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java @@ -180,10 +180,12 @@ private String[] makeJdbCmdLine (String classToExecute) { } else /* LaunchingConnector or DefaultConnector */ { connect.append("vmexec=" + argumentHandler.getLaunchExecName().trim()); + connect.append(",options="); + connect.append(" \"-cp\""); + connect.append(" \"" + System.getProperty("test.class.path") + "\""); + String debuggeeOpts = argumentHandler.getDebuggeeOptions(); if (debuggeeOpts.trim().length() > 0) { - //connect.append(",options=" + debuggeeOpts.trim()); - connect.append(",options="); for (String arg : debuggeeOpts.split("\\s+")) { connect.append(" \""); connect.append(arg); From 5079c38ddf345b21d8cb1c959bc36c4341e11da6 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 12 Aug 2024 22:12:01 +0000 Subject: [PATCH 48/84] 8338160: Fix -Wzero-as-null-pointer-constant warnings in management.cpp Reviewed-by: dholmes --- src/hotspot/share/services/management.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index 2c9f36c098d..ac7e1daf397 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -1820,7 +1820,7 @@ JVM_END // of a given length and return the objArrayOop static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRAPS) { if (array == nullptr) { - THROW_(vmSymbols::java_lang_NullPointerException(), 0); + THROW_NULL(vmSymbols::java_lang_NullPointerException()); } objArrayOop oa = objArrayOop(JNIHandles::resolve_non_null(array)); @@ -1828,16 +1828,16 @@ static objArrayOop get_memory_usage_objArray(jobjectArray array, int length, TRA // array must be of the given length if (length != array_h->length()) { - THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), - "The length of the given MemoryUsage array does not match the number of memory pools.", 0); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + "The length of the given MemoryUsage array does not match the number of memory pools."); } // check if the element of array is of type MemoryUsage class Klass* usage_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_NULL); Klass* element_klass = ObjArrayKlass::cast(array_h->klass())->element_klass(); if (element_klass != usage_klass) { - THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), - "The element type is not MemoryUsage class", 0); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + "The element type is not MemoryUsage class"); } return array_h(); From e70c9bccaae375be1ee6812dabc9fbaff01a6ab0 Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Mon, 12 Aug 2024 23:00:04 +0000 Subject: [PATCH 49/84] 8338248: PartialArrayStateAllocator::Impl leaks Arena array Reviewed-by: kbarrett, shade --- src/hotspot/share/gc/shared/partialArrayState.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/gc/shared/partialArrayState.cpp b/src/hotspot/share/gc/shared/partialArrayState.cpp index 583c5dede40..fd23a320222 100644 --- a/src/hotspot/share/gc/shared/partialArrayState.cpp +++ b/src/hotspot/share/gc/shared/partialArrayState.cpp @@ -100,6 +100,7 @@ PartialArrayStateAllocator::Impl::~Impl() { for (uint i = 0; i < _num_workers; ++i) { _arenas[i].~Arena(); } + FREE_C_HEAP_ARRAY(Arena*, _arenas); } PartialArrayState* PartialArrayStateAllocator::Impl::allocate(uint worker_id, From d77e6fe45c7b834db457a772ce0bea514d2e44f3 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 13 Aug 2024 05:46:38 +0000 Subject: [PATCH 50/84] 8338154: Fix -Wzero-as-null-pointer-constant warnings in gtest framework Reviewed-by: ihse, dholmes, jwaters --- make/hotspot/lib/CompileGtest.gmk | 3 ++- test/hotspot/gtest/gtestMain.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/make/hotspot/lib/CompileGtest.gmk b/make/hotspot/lib/CompileGtest.gmk index 696adb0c95f..424743ba279 100644 --- a/make/hotspot/lib/CompileGtest.gmk +++ b/make/hotspot/lib/CompileGtest.gmk @@ -57,7 +57,8 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \ $(GTEST_FRAMEWORK_SRC)/googletest/src \ $(GTEST_FRAMEWORK_SRC)/googlemock/src, \ INCLUDE_FILES := gtest-all.cc gmock-all.cc, \ - DISABLED_WARNINGS_gcc := undef unused-result format-nonliteral maybe-uninitialized, \ + DISABLED_WARNINGS_gcc := undef unused-result format-nonliteral \ + maybe-uninitialized zero-as-null-pointer-constant, \ DISABLED_WARNINGS_clang := undef unused-result format-nonliteral, \ DEFAULT_CFLAGS := false, \ CFLAGS := $(JVM_CFLAGS) \ diff --git a/test/hotspot/gtest/gtestMain.cpp b/test/hotspot/gtest/gtestMain.cpp index bc8ca29f72d..0bd251e8094 100644 --- a/test/hotspot/gtest/gtestMain.cpp +++ b/test/hotspot/gtest/gtestMain.cpp @@ -336,7 +336,7 @@ static void run_in_new_thread(const args_t* args) { extern "C" void* thread_wrapper(void* p) { const args_t* const p_args = (const args_t*) p; runUnitTestsInner(p_args->argc, p_args->argv); - return 0; + return nullptr; } static void run_in_new_thread(const args_t* args) { From 73ddb7deab26c526337ec6e7cd5f528f698a552c Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Tue, 13 Aug 2024 05:52:44 +0000 Subject: [PATCH 51/84] 8335628: C2 SuperWord: cleanup: remove SuperWord::longer_type_for_conversion Reviewed-by: chagedorn, kvn --- src/hotspot/share/opto/superword.cpp | 25 +------------------------ src/hotspot/share/opto/superword.hpp | 3 --- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 0e1328a4485..2a43d2ec0af 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -691,9 +691,7 @@ bool SuperWord::can_pack_into_pair(Node* s1, Node* s2) { BasicType bt2 = velt_basic_type(s2); if(!is_java_primitive(bt1) || !is_java_primitive(bt2)) return false; - BasicType longer_bt = longer_type_for_conversion(s1); - if (Matcher::max_vector_size_auto_vectorization(bt1) < 2 || - (longer_bt != T_ILLEGAL && Matcher::max_vector_size_auto_vectorization(longer_bt) < 2)) { + if (Matcher::max_vector_size_auto_vectorization(bt1) < 2) { return false; // No vectors for this type } @@ -2442,27 +2440,6 @@ VStatus VLoopBody::construct() { return VStatus::make_success(); } -BasicType SuperWord::longer_type_for_conversion(Node* n) const { - if (!(VectorNode::is_convert_opcode(n->Opcode()) || - VectorNode::is_scalar_op_that_returns_int_but_vector_op_returns_long(n->Opcode())) || - !in_bb(n->in(1))) { - return T_ILLEGAL; - } - assert(in_bb(n), "must be in the bb"); - BasicType src_t = velt_basic_type(n->in(1)); - BasicType dst_t = velt_basic_type(n); - // Do not use superword for non-primitives. - // Superword does not support casting involving unsigned types. - if (!is_java_primitive(src_t) || is_unsigned_subword_type(src_t) || - !is_java_primitive(dst_t) || is_unsigned_subword_type(dst_t)) { - return T_ILLEGAL; - } - int src_size = type2aelembytes(src_t); - int dst_size = type2aelembytes(dst_t); - return src_size == dst_size ? T_ILLEGAL - : (src_size > dst_size ? src_t : dst_t); -} - void VLoopTypes::compute_vector_element_type() { #ifndef PRODUCT if (_vloop.is_trace_vector_element_type()) { diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 65f87082525..8b24e0cf3a1 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -623,9 +623,6 @@ class SuperWord : public ResourceObj { // Is use->in(u_idx) a vector use? bool is_vector_use(Node* use, int u_idx) const; - // Return the longer type for vectorizable type-conversion node or illegal type for other nodes. - BasicType longer_type_for_conversion(Node* n) const; - bool is_velt_basic_type_compatible_use_def(Node* use, Node* def) const; bool schedule_and_apply() const; From c27a8c8c8b867e6812b905f6154762802a498dbd Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Tue, 13 Aug 2024 05:52:58 +0000 Subject: [PATCH 52/84] 8338124: C2 SuperWord: MulAddS2I input permutation still partially broken after JDK-8333840 Reviewed-by: chagedorn, thartmann, kvn --- src/hotspot/share/opto/superword.cpp | 2 +- .../loopopts/superword/TestMulAddS2I.java | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 2a43d2ec0af..bb5fed78b02 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2270,7 +2270,7 @@ Node_List* PackSet::strided_pack_input_at_index_or_null(const Node_List* pack, c return nullptr; // size mismatch } - for (uint i = 1; i < pack->size(); i++) { + for (uint i = 0; i < pack->size(); i++) { if (pack->at(i)->in(index) != pack_in->at(i * stride + offset)) { return nullptr; // use-def mismatch } diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java index e0f073c7f8f..fb99fc5983a 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java @@ -53,6 +53,7 @@ public class TestMulAddS2I { static final int[] GOLDEN_J; static final int[] GOLDEN_K; static final int[] GOLDEN_L; + static final int[] GOLDEN_M; static { for (int i = 0; i < RANGE; i++) { @@ -71,6 +72,7 @@ public class TestMulAddS2I { GOLDEN_J = testj(new int[ITER]); GOLDEN_K = testk(new int[ITER]); GOLDEN_L = testl(new int[ITER]); + GOLDEN_M = testm(new int[ITER]); } @@ -80,7 +82,7 @@ public static void main(String[] args) { } @Run(test = {"testa", "testb", "testc", "testd", "teste", "testf", "testg", "testh", - "testi", "testj", "testk", "testl"}) + "testi", "testj", "testk", "testl", "testm"}) @Warmup(0) public static void run() { compare(testa(), GOLDEN_A, "testa"); @@ -95,6 +97,7 @@ public static void run() { compare(testj(new int[ITER]), GOLDEN_J, "testj"); compare(testk(new int[ITER]), GOLDEN_K, "testk"); compare(testl(new int[ITER]), GOLDEN_L, "testl"); + compare(testm(new int[ITER]), GOLDEN_M, "testm"); } public static void compare(int[] out, int[] golden, String name) { @@ -299,4 +302,17 @@ public static int[] testl(int[] out) { return out; } + @Test + @IR(counts = {IRNode.MUL_ADD_S2I, "> 0"}, + applyIfCPUFeatureOr = {"sse2", "true", "asimd", "true"}) + @IR(counts = {IRNode.MUL_ADD_VS2VI, "= 0"}) + public static int[] testm(int[] out) { + for (int i = 0; i < ITER-4; i+=4) { + // Unrolled, with some swaps that prevent vectorization. + out[i+0] += ((sArr1[2*i+0] * sArr2[2*i+1]) + (sArr1[2*i+1] * sArr2[2*i+0])); // bad + out[i+1] += ((sArr1[2*i+2] * sArr2[2*i+2]) + (sArr1[2*i+3] * sArr2[2*i+3])); // ok + // 2-element gap + } + return out; + } } From 73f7a5f15dbba54a98f3916ff1190520ac07874d Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 13 Aug 2024 07:27:49 +0000 Subject: [PATCH 53/84] 8338155: Fix -Wzero-as-null-pointer-constant warnings involving PTHREAD_MUTEX_INITIALIZER Reviewed-by: dholmes, dlong --- src/hotspot/os/linux/os_perf_linux.cpp | 5 ++++- src/hotspot/os/posix/threadCritical_posix.cpp | 8 +++++++- src/hotspot/share/utilities/compilerWarnings.hpp | 6 +++++- src/hotspot/share/utilities/compilerWarnings_gcc.hpp | 5 ++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp index 87abbebe25f..a31a58e55af 100644 --- a/src/hotspot/os/linux/os_perf_linux.cpp +++ b/src/hotspot/os/linux/os_perf_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -430,7 +430,10 @@ static int get_boot_time(uint64_t* time) { } static int perf_context_switch_rate(double* rate) { + PRAGMA_DIAG_PUSH + PRAGMA_ZERO_AS_NULL_POINTER_CONSTANT_IGNORED static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER; + PRAGMA_DIAG_POP static uint64_t bootTime; static uint64_t lastTimeNanos; static uint64_t lastSwitches; diff --git a/src/hotspot/os/posix/threadCritical_posix.cpp b/src/hotspot/os/posix/threadCritical_posix.cpp index 45eba4c1585..cd3b42e71ba 100644 --- a/src/hotspot/os/posix/threadCritical_posix.cpp +++ b/src/hotspot/os/posix/threadCritical_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "runtime/javaThread.hpp" #include "runtime/threadCritical.hpp" +#include "utilities/compilerWarnings.hpp" // put OS-includes here # include @@ -35,7 +36,12 @@ // static pthread_t tc_owner = 0; + +PRAGMA_DIAG_PUSH +PRAGMA_ZERO_AS_NULL_POINTER_CONSTANT_IGNORED static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER; +PRAGMA_DIAG_POP + static int tc_count = 0; ThreadCritical::ThreadCritical() { diff --git a/src/hotspot/share/utilities/compilerWarnings.hpp b/src/hotspot/share/utilities/compilerWarnings.hpp index 28954843dc3..ddcaf022fa6 100644 --- a/src/hotspot/share/utilities/compilerWarnings.hpp +++ b/src/hotspot/share/utilities/compilerWarnings.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,10 @@ #define PRAGMA_NONNULL_IGNORED #endif +#ifndef PRAGMA_ZERO_AS_NULL_POINTER_CONSTANT_IGNORED +#define PRAGMA_ZERO_AS_NULL_POINTER_CONSTANT_IGNORED +#endif + // Support warnings for use of certain C functions, except where explicitly // permitted. // diff --git a/src/hotspot/share/utilities/compilerWarnings_gcc.hpp b/src/hotspot/share/utilities/compilerWarnings_gcc.hpp index 53373ec628a..1dd5892e4c3 100644 --- a/src/hotspot/share/utilities/compilerWarnings_gcc.hpp +++ b/src/hotspot/share/utilities/compilerWarnings_gcc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,6 +67,9 @@ #define PRAGMA_NONNULL_IGNORED PRAGMA_DISABLE_GCC_WARNING("-Wnonnull") +#define PRAGMA_ZERO_AS_NULL_POINTER_CONSTANT_IGNORED \ + PRAGMA_DISABLE_GCC_WARNING("-Wzero-as-null-pointer-constant") + #if (__GNUC__ >= 10) // TODO: Re-enable warning attribute for Clang once // https://github.com/llvm/llvm-project/issues/56519 is fixed and released. From 5bf27098e22172ed5d3ec0c43fe0553f8322c4b1 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 13 Aug 2024 08:10:29 +0000 Subject: [PATCH 54/84] 8334475: UnsafeIntrinsicsTest.java#ZGenerationalDebug assert(!assert_on_failure) failed: Has low-order bits set Reviewed-by: stefank, eosterlund, aboldtch --- .../windows_aarch64/copy_windows_aarch64.hpp | 63 +++++++------------ 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp b/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp index ce2ad2d046f..96a34fe967b 100644 --- a/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp +++ b/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp @@ -26,8 +26,27 @@ #ifndef OS_CPU_WINDOWS_AARCH64_COPY_WINDOWS_AARCH64_HPP #define OS_CPU_WINDOWS_AARCH64_COPY_WINDOWS_AARCH64_HPP +#include "runtime/atomic.hpp" + #include +template +static void pd_conjoint_atomic_helper(const T* from, T* to, size_t count) { + if (from > to) { + while (count-- > 0) { + // Copy forwards + Atomic::store(to++, Atomic::load(from++)); + } + } else { + from += count - 1; + to += count - 1; + while (count-- > 0) { + // Copy backwards + Atomic::store(to--, Atomic::load(from--)); + } + } +} + static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { (void)memmove(to, from, count * HeapWordSize); } @@ -71,55 +90,19 @@ static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { } static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { - if (from > to) { - while (count-- > 0) { - // Copy forwards - *to++ = *from++; - } - } else { - from += count - 1; - to += count - 1; - while (count-- > 0) { - // Copy backwards - *to-- = *from--; - } - } + pd_conjoint_atomic_helper(from, to, count); } static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { - if (from > to) { - while (count-- > 0) { - // Copy forwards - *to++ = *from++; - } - } else { - from += count - 1; - to += count - 1; - while (count-- > 0) { - // Copy backwards - *to-- = *from--; - } - } + pd_conjoint_atomic_helper(from, to, count); } static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { - pd_conjoint_oops_atomic((const oop*)from, (oop*)to, count); + pd_conjoint_atomic_helper(from, to, count); } static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { - if (from > to) { - while (count-- > 0) { - // Copy forwards - *to++ = *from++; - } - } else { - from += count - 1; - to += count - 1; - while (count-- > 0) { - // Copy backwards - *to-- = *from--; - } - } + pd_conjoint_atomic_helper(from, to, count); } static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { From ba69ed7c58fcf99ed18dfd8840125ddcac9460bb Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 13 Aug 2024 08:11:47 +0000 Subject: [PATCH 55/84] 8338202: Shenandoah: Improve handshake closure labels Reviewed-by: rkennke, ysr, wkemper --- src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp | 2 +- .../share/gc/shenandoah/shenandoahConcurrentMark.cpp | 2 +- src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp | 6 +++--- src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp | 2 +- src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index ac2e732052a..86d6d91f72c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -823,7 +823,7 @@ void ShenandoahConcurrentGC::op_weak_roots() { // Perform handshake to flush out dead oops { ShenandoahTimingsTracker t(ShenandoahPhaseTimings::conc_weak_roots_rendezvous); - heap->rendezvous_threads(); + heap->rendezvous_threads("Shenandoah Concurrent Weak Roots"); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index 31157616e0e..dde446d824b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -179,7 +179,7 @@ class ShenandoahFlushSATBHandshakeClosure : public HandshakeClosure { SATBMarkQueueSet& _qset; public: ShenandoahFlushSATBHandshakeClosure(SATBMarkQueueSet& qset) : - HandshakeClosure("Shenandoah Flush SATB Handshake"), + HandshakeClosure("Shenandoah Flush SATB"), _qset(qset) {} void do_thread(Thread* thread) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index eb6de9719dc..0a20307abcb 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1744,12 +1744,12 @@ void ShenandoahHeap::parallel_heap_region_iterate(ShenandoahHeapRegionClosure* b class ShenandoahRendezvousClosure : public HandshakeClosure { public: - inline ShenandoahRendezvousClosure() : HandshakeClosure("ShenandoahRendezvous") {} + inline ShenandoahRendezvousClosure(const char* name) : HandshakeClosure(name) {} inline void do_thread(Thread* thread) {} }; -void ShenandoahHeap::rendezvous_threads() { - ShenandoahRendezvousClosure cl; +void ShenandoahHeap::rendezvous_threads(const char* name) { + ShenandoahRendezvousClosure cl(name); Handshake::execute(&cl); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index f3625da218c..86bd7b83bbe 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -400,7 +400,7 @@ class ShenandoahHeap : public CollectedHeap, public ShenandoahSpaceInfo { void update_heap_region_states(bool concurrent); void rebuild_free_set(bool concurrent); - void rendezvous_threads(); + void rendezvous_threads(const char* name); void recycle_trash(); public: void notify_gc_progress(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp index 02a7fbeb8b5..f33b76bcd4e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp @@ -168,7 +168,7 @@ void ShenandoahUnload::unload() { // Make sure stale metadata and nmethods are no longer observable { ShenandoahTimingsTracker t(ShenandoahPhaseTimings::conc_class_unload_rendezvous); - heap->rendezvous_threads(); + heap->rendezvous_threads("Shenandoah Class Unloading"); } // Purge stale metadata and nmethods that were unlinked From fbe4cc96e223882a18c7ff666fe6f68b3fa2cfe4 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 13 Aug 2024 09:51:08 +0000 Subject: [PATCH 56/84] 8336384: AbstractQueuedSynchronizer.acquire should cancel acquire when failing due to a LinkageError or other errors Reviewed-by: alanb --- .../locks/AbstractQueuedLongSynchronizer.java | 19 ++++++++++++------- .../locks/AbstractQueuedSynchronizer.java | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java index f4d7d0c08c0..2de1d17e7c1 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java @@ -369,14 +369,19 @@ final int acquire(Node node, long arg, boolean shared, } else if (node.status == 0) { node.status = WAITING; // enable signal and recheck } else { - long nanos; spins = postSpins = (byte)((postSpins << 1) | 1); - if (!timed) - LockSupport.park(this); - else if ((nanos = time - System.nanoTime()) > 0L) - LockSupport.parkNanos(this, nanos); - else - break; + try { + long nanos; + if (!timed) + LockSupport.park(this); + else if ((nanos = time - System.nanoTime()) > 0L) + LockSupport.parkNanos(this, nanos); + else + break; + } catch (Error | RuntimeException ex) { + cancelAcquire(node, interrupted, interruptible); // cancel & rethrow + throw ex; + } node.clearStatus(); if ((interrupted |= Thread.interrupted()) && interruptible) break; diff --git a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java index 1f51419f94c..2ea0d3ed3b0 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -748,14 +748,19 @@ final int acquire(Node node, int arg, boolean shared, } else if (node.status == 0) { node.status = WAITING; // enable signal and recheck } else { - long nanos; spins = postSpins = (byte)((postSpins << 1) | 1); - if (!timed) - LockSupport.park(this); - else if ((nanos = time - System.nanoTime()) > 0L) - LockSupport.parkNanos(this, nanos); - else - break; + try { + long nanos; + if (!timed) + LockSupport.park(this); + else if ((nanos = time - System.nanoTime()) > 0L) + LockSupport.parkNanos(this, nanos); + else + break; + } catch (Error | RuntimeException ex) { + cancelAcquire(node, interrupted, interruptible); // cancel & rethrow + throw ex; + } node.clearStatus(); if ((interrupted |= Thread.interrupted()) && interruptible) break; From ff8a9f9267c480fe0be8470cda870fd77763fb31 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 13 Aug 2024 11:48:50 +0000 Subject: [PATCH 57/84] 8337318: Deoptimization::relock_objects fails assert(monitor->owner() == Thread::current()) failed: must be Co-authored-by: Richard Reingruber Reviewed-by: rrich, dholmes, shade, pchilanomate --- src/hotspot/share/runtime/synchronizer.cpp | 4 +- test/jdk/com/sun/jdi/EATests.java | 83 +++++++++++++++++++++- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 2d45163d0f4..b4ff263d455 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -596,8 +596,8 @@ bool ObjectSynchronizer::enter_fast_impl(Handle obj, BasicLock* lock, JavaThread log_info(monitorinflation)("LockStack capacity exceeded, inflating."); ObjectMonitor* monitor = inflate_for(locking_thread, lock_stack.bottom(), inflate_cause_vm_internal); - assert(monitor->owner() == Thread::current(), "must be owner=" PTR_FORMAT " current=" PTR_FORMAT " mark=" PTR_FORMAT, - p2i(monitor->owner()), p2i(Thread::current()), monitor->object()->mark_acquire().value()); + assert(monitor->owner() == locking_thread, "must be owner=" PTR_FORMAT " locking_thread=" PTR_FORMAT " mark=" PTR_FORMAT, + p2i(monitor->owner()), p2i(locking_thread), monitor->object()->mark_acquire().value()); assert(!lock_stack.is_full(), "must have made room here"); } diff --git a/test/jdk/com/sun/jdi/EATests.java b/test/jdk/com/sun/jdi/EATests.java index 72859481659..adeb2174143 100644 --- a/test/jdk/com/sun/jdi/EATests.java +++ b/test/jdk/com/sun/jdi/EATests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 SAP SE. All rights reserved. + * Copyright (c) 2020, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -288,6 +288,7 @@ public static void main(String[] args) { // Relocking test cases new EARelockingSimpleTarget() .run(); + new EARelockingWithManyLightweightLocksTarget() .run(); new EARelockingSimpleWithAccessInOtherThreadTarget() .run(); new EARelockingSimpleWithAccessInOtherThread_02_DynamicCall_Target() .run(); new EARelockingRecursiveTarget() .run(); @@ -413,6 +414,7 @@ protected void runTests() throws Exception { // Relocking test cases new EARelockingSimple() .run(this); + new EARelockingWithManyLightweightLocks() .run(this); new EARelockingSimpleWithAccessInOtherThread() .run(this); new EARelockingSimpleWithAccessInOtherThread_02_DynamicCall() .run(this); new EARelockingRecursive() .run(this); @@ -1797,6 +1799,85 @@ public void dontinline_testMethod() { ///////////////////////////////////////////////////////////////////////////// +/** + * Like {@link EARelockingSimple}. The difference is that there are many + * lightweight locked objects when the relocking is done. With + * -XX:LockingMode=2 the lock stack of the thread will be full + * because of this. + */ + +class EARelockingWithManyLightweightLocks extends EATestCaseBaseDebugger { + + public void runTestCase() throws Exception { + BreakpointEvent bpe = resumeTo(TARGET_TESTCASE_BASE_NAME, "dontinline_brkpt", "()V"); + printStack(bpe.thread()); + @SuppressWarnings("unused") + ObjectReference o = getLocalRef(bpe.thread().frame(1), XYVAL_NAME, "l1"); + } +} + +class EARelockingWithManyLightweightLocksTarget extends EATestCaseBaseTarget { + + static class Lock { + } + + public static Lock L0, L1, L2, L3, L4, L5, L6, L7, L8, L9; + + void allocateLocks() { + L0 = new Lock(); + L1 = new Lock(); + L2 = new Lock(); + L3 = new Lock(); + L4 = new Lock(); + L5 = new Lock(); + L6 = new Lock(); + L7 = new Lock(); + L8 = new Lock(); + L9 = new Lock(); + } + + @Override + public void setUp() { + super.setUp(); + allocateLocks(); + } + + @Override + public void warmupDone() { + super.warmupDone(); + allocateLocks(); // get rid of already inflated ones + } + + public void dontinline_testMethod() { + XYVal l1 = new XYVal(4, 2); + synchronized(L0) { + synchronized(L1) { + synchronized(L2) { + synchronized(L3) { + synchronized(L4) { + synchronized(L5) { + synchronized(L6) { + synchronized(L7) { + synchronized(L8) { + synchronized(L9) { + synchronized (l1) { + dontinline_brkpt(); + } + } + } + } + } + } + } + } + } + } + } + } +} + +///////////////////////////////////////////////////////////////////////////// + // The debugger reads and publishes an object with eliminated locking to an instance field. // A 2nd thread in the debuggee finds it there and changes its state using a synchronized method. // Without eager relocking the accesses are unsynchronized which can be observed. From 76e33b6c1517599e14ee34371c945aafcd752e4e Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 13 Aug 2024 13:13:14 +0000 Subject: [PATCH 58/84] 8336148: Test runtime/locking/TestRecursiveMonitorChurn.java failed: Unexpected Inflation Reviewed-by: dholmes, eosterlund --- .../runtime/locking/TestRecursiveMonitorChurn.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java index 19dd90015bf..806f32aad88 100644 --- a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java +++ b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java @@ -70,6 +70,18 @@ public static void main(String[] args) { if (pre_monitor_count != post_monitor_count) { final long monitor_count_change = post_monitor_count - pre_monitor_count; System.out.println("Unexpected change in monitor count: " + monitor_count_change); + + // Intermittent deflation and inflation may occur due to running the test + // with stress flags (like DeoptimizeALot) or with added instrumentation + // which runs in the same VM. + // An arbitrary fuzzy max difference of 10 (= 0.01% of COUNT) is chosen to + // allow for these occurrences to be skipped while still catching regressions. + final long fuzzy_max_difference = 10; + if (Math.abs(monitor_count_change) < fuzzy_max_difference) { + final String type = monitor_count_change < 0 ? "deflation" : "inflation"; + throw new SkippedException("Intermittent " + type + " detected. Invalid test."); + } + if (monitor_count_change < 0) { throw new RuntimeException("Unexpected Deflation"); } From 877fd5a768647790d0a43aaca247043bae70d708 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Tue, 13 Aug 2024 14:43:44 +0000 Subject: [PATCH 59/84] 8337595: Remove empty statements in src/hotspot/share/memory/metaspace Reviewed-by: stefank, dholmes, jwaters --- src/hotspot/share/memory/metaspace/metaspaceCommon.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp b/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp index eae75e8194c..511f4e6e092 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp +++ b/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp @@ -85,7 +85,7 @@ void print_percentage(outputStream* st, size_t total, size_t part); SIZE_FORMAT_X " is not aligned to " \ SIZE_FORMAT_X, (size_t)(uintptr_t)value, (size_t)(alignment)) #define assert_is_aligned_metaspace_pointer(p) \ - assert_is_aligned((p), metaspace::AllocationAlignmentByteSize); + assert_is_aligned((p), metaspace::AllocationAlignmentByteSize) #else #define assert_is_aligned(value, alignment) #define assert_is_aligned_metaspace_pointer(pointer) @@ -141,8 +141,8 @@ void print_number_of_classes(outputStream* out, uintx classes, uintx classes_sha #define HAVE_UL #ifdef HAVE_UL -#define UL(level, message) log_##level(metaspace)(LOGFMT ": " message, LOGFMT_ARGS); -#define UL2(level, message, ...) log_##level(metaspace)(LOGFMT ": " message, LOGFMT_ARGS, __VA_ARGS__); +#define UL(level, message) log_##level(metaspace)(LOGFMT ": " message, LOGFMT_ARGS) +#define UL2(level, message, ...) log_##level(metaspace)(LOGFMT ": " message, LOGFMT_ARGS, __VA_ARGS__) #else #define UL(level, ...) #define UL2(level, ...) From 9e282e5c966a9c065de8b901b7d30bb5c9ccf243 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Tue, 13 Aug 2024 15:05:49 +0000 Subject: [PATCH 60/84] 8337998: CompletionFailure in getEnclosingType attaching type annotations Reviewed-by: vromero --- .../com/sun/tools/javac/jvm/ClassReader.java | 15 ++- .../tools/javac/resources/compiler.properties | 5 + .../CompletionErrorOnEnclosingType.java | 98 +++++++++++++++++++ .../tools/javac/diags/examples.not-yet.txt | 1 + 4 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 test/langtools/tools/javac/annotations/typeAnnotations/CompletionErrorOnEnclosingType.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index fcc1efda8dc..bd05cf91e91 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -62,6 +62,7 @@ import com.sun.tools.javac.jvm.ClassFile.Version; import com.sun.tools.javac.jvm.PoolConstant.NameAndType; import com.sun.tools.javac.main.Option; +import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import com.sun.tools.javac.resources.CompilerProperties.Warnings; import com.sun.tools.javac.util.*; @@ -2311,9 +2312,17 @@ public void run() { * 4.7.20-A target_type to locate the correct type to rewrite, and then interpreting the JVMS * 4.7.20.2 type_path to associate the annotation with the correct contained type. */ - private static void addTypeAnnotationsToSymbol( - Symbol s, List attributes) { - new TypeAnnotationSymbolVisitor(attributes).visit(s, null); + private void addTypeAnnotationsToSymbol(Symbol s, List attributes) { + try { + new TypeAnnotationSymbolVisitor(attributes).visit(s, null); + } catch (CompletionFailure ex) { + JavaFileObject prev = log.useSource(currentClassFile); + try { + log.error(Errors.CantAttachTypeAnnotations(attributes, s.owner, s.name, ex.getDetailValue())); + } finally { + log.useSource(prev); + } + } } private static class TypeAnnotationSymbolVisitor diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 8576106e15f..10f06ad7017 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2345,6 +2345,11 @@ compiler.warn.annotation.method.not.found=\ compiler.warn.annotation.method.not.found.reason=\ Cannot find annotation method ''{1}()'' in type ''{0}'': {2} +# 0: list of annotation, 1: symbol, 2: name, 3: message segment +compiler.err.cant.attach.type.annotations=\ + Cannot attach type annotations {0} to {1}.{2}:\n\ + {3} + # 0: file object, 1: symbol, 2: name compiler.warn.unknown.enum.constant=\ unknown enum constant {1}.{2} diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/CompletionErrorOnEnclosingType.java b/test/langtools/tools/javac/annotations/typeAnnotations/CompletionErrorOnEnclosingType.java new file mode 100644 index 00000000000..11b4e1ccbd4 --- /dev/null +++ b/test/langtools/tools/javac/annotations/typeAnnotations/CompletionErrorOnEnclosingType.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2024, Alphabet LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8337998 + * @summary CompletionFailure in getEnclosingType attaching type annotations + * @library /tools/javac/lib /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + */ + +import toolbox.*; +import toolbox.Task.*; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +public class CompletionErrorOnEnclosingType { + ToolBox tb = new ToolBox(); + + public static void main(String... args) throws Exception { + CompletionErrorOnEnclosingType t = new CompletionErrorOnEnclosingType(); + t.testMissingEnclosingType(); + } + + void testMissingEnclosingType() throws Exception { + String annoSrc = + """ + import static java.lang.annotation.ElementType.TYPE_USE; + import java.lang.annotation.Target; + @Target(TYPE_USE) + @interface Anno {} + + class A {} + + class B { + private @Anno A a; + } + """; + String cSrc = + """ + class C { + B b; + } + """; + + Path base = Paths.get("."); + Path src = base.resolve("src"); + tb.createDirectories(src); + tb.writeJavaFiles(src, annoSrc, cSrc); + Path out = base.resolve("out"); + tb.createDirectories(out); + new JavacTask(tb).outdir(out).files(tb.findJavaFiles(src)).run(); + + // now if we remove A.class there will be an error but javac should not crash + tb.deleteFiles(out.resolve("A.class")); + List log = + new JavacTask(tb) + .outdir(out) + .classpath(out) + .options("-XDrawDiagnostics") + .files(src.resolve("C.java")) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + var expectedOutput = + List.of( + "B.class:-:-: compiler.err.cant.attach.type.annotations: @Anno, B, a," + + " (compiler.misc.class.file.not.found: A)", + "1 error"); + if (!expectedOutput.equals(log)) { + throw new Exception("expected output not found: " + log); + } + } +} diff --git a/test/langtools/tools/javac/diags/examples.not-yet.txt b/test/langtools/tools/javac/diags/examples.not-yet.txt index 9a447927761..b2603338509 100644 --- a/test/langtools/tools/javac/diags/examples.not-yet.txt +++ b/test/langtools/tools/javac/diags/examples.not-yet.txt @@ -41,6 +41,7 @@ compiler.err.signature.doesnt.match.intf # UNUSED compiler.err.signature.doesnt.match.supertype # UNUSED compiler.err.source.cant.overwrite.input.file compiler.err.stack.sim.error +compiler.err.cant.attach.type.annotations # bad class file compiler.err.type.var.more.than.once # UNUSED compiler.err.type.var.more.than.once.in.result # UNUSED compiler.err.unexpected.type From 6af1d6ff210b3ddbc7d1585428b49631248a500b Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Tue, 13 Aug 2024 15:14:06 +0000 Subject: [PATCH 61/84] 8335927: Revisit AnnotationConstantValueEntry and AnnotationValue.OfConstant Reviewed-by: asotona --- .../java/lang/classfile/AnnotationValue.java | 347 +++++++++++++----- .../AnnotationConstantValueEntry.java | 19 +- .../constantpool/ConstantPoolBuilder.java | 19 - .../classfile/impl/AnnotationImpl.java | 47 +-- .../classfile/impl/AnnotationReader.java | 4 +- .../classfile/impl/ClassPrinterImpl.java | 20 +- test/jdk/jdk/classfile/AnnotationTest.java | 54 +-- test/jdk/jdk/classfile/ClassPrinterTest.java | 11 +- .../helpers/RebuildingTransformation.java | 4 +- .../classfile/AnonymousClassTest.java | 2 +- .../AnnotationDefaultVerifier.java | 4 +- .../annotations/TestAnnotationInfo.java | 8 +- 12 files changed, 358 insertions(+), 181 deletions(-) diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java index 919c8a0441d..a4a1c218ac1 100644 --- a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java +++ b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java @@ -26,6 +26,7 @@ import java.lang.classfile.constantpool.AnnotationConstantValueEntry; import java.lang.classfile.constantpool.DoubleEntry; +import java.lang.classfile.constantpool.DynamicConstantPoolEntry; import java.lang.classfile.constantpool.FloatEntry; import java.lang.classfile.constantpool.IntegerEntry; import java.lang.classfile.constantpool.LongEntry; @@ -34,7 +35,7 @@ import jdk.internal.classfile.impl.TemporaryConstantPool; import java.lang.constant.ClassDesc; -import java.lang.constant.ConstantDesc; +import java.lang.constant.Constable; import java.util.ArrayList; import java.util.List; import jdk.internal.javac.PreviewFeature; @@ -49,191 +50,373 @@ * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) -public sealed interface AnnotationValue - permits AnnotationValue.OfAnnotation, AnnotationValue.OfArray, - AnnotationValue.OfConstant, AnnotationValue.OfClass, - AnnotationValue.OfEnum { +public sealed interface AnnotationValue { /** - * Models an annotation-valued element + * Models an annotation-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ANNOTATION}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfAnnotation extends AnnotationValue permits AnnotationImpl.OfAnnotationImpl { - /** {@return the annotation} */ + /** {@return the annotation value} */ Annotation annotation(); } /** - * Models an array-valued element + * Models an array-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ARRAY}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfArray extends AnnotationValue permits AnnotationImpl.OfArrayImpl { - /** {@return the values} */ + /** + * {@return the array elements of the array value} + * + * @apiNote + * All array elements derived from Java source code have the same type, + * which must not be an array type. ({@jls 9.6.1}) + */ List values(); } /** - * Models a constant-valued element + * Models a constant-valued element. * * @sealedGraph * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfConstant extends AnnotationValue - permits AnnotationValue.OfString, AnnotationValue.OfDouble, - AnnotationValue.OfFloat, AnnotationValue.OfLong, - AnnotationValue.OfInteger, AnnotationValue.OfShort, - AnnotationValue.OfCharacter, AnnotationValue.OfByte, - AnnotationValue.OfBoolean, AnnotationImpl.OfConstantImpl { - /** {@return the constant} */ + sealed interface OfConstant + extends AnnotationValue + permits OfString, OfDouble, OfFloat, OfLong, OfInt, OfShort, OfChar, OfByte, + OfBoolean, AnnotationImpl.OfConstantImpl { + /** + * {@return the constant pool entry backing this constant element} + * + * @apiNote + * Different types of constant values may share the same type of entry. + * For example, {@link OfInt} and {@link OfChar} are both + * backed by {@link IntegerEntry}. Use {@link #resolvedValue + * resolvedValue()} for a value of accurate type. + */ AnnotationConstantValueEntry constant(); - /** {@return the constant} */ - ConstantDesc constantValue(); - } - /** - * Models a constant-valued element + /** + * {@return the resolved live constant value, as an object} The type of + * the returned value may be a wrapper class or {@link String}. + * + * @apiNote + * The returned object, despite being {@link Constable}, may not + * {@linkplain Constable#describeConstable() describe} the right constant + * for encoding the annotation value in a class file. For example, + * {@link Character} returned by {@link OfChar} describes itself as a + * {@link DynamicConstantPoolEntry}, but it is actually backed by + * {@link IntegerEntry} in annotation format. + * Use {@link #constant constant()} for a correct constant pool representation. + */ + Constable resolvedValue(); + } + + /** + * Models a string-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_STRING}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfString extends AnnotationValue.OfConstant + sealed interface OfString extends OfConstant permits AnnotationImpl.OfStringImpl { - /** {@return the constant} */ + /** {@return the backing UTF8 entry} */ + @Override + Utf8Entry constant(); + + /** {@return the constant string value} */ String stringValue(); + + /** + * {@return the resolved string value} + * + * @implSpec + * This method returns the same as {@link #stringValue()}. + */ + @Override + default String resolvedValue() { + return stringValue(); + } } /** - * Models a constant-valued element + * Models a double-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_DOUBLE}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfDouble extends AnnotationValue.OfConstant + sealed interface OfDouble extends OfConstant permits AnnotationImpl.OfDoubleImpl { - /** {@return the constant} */ + /** {@return the backing double entry} */ + @Override + DoubleEntry constant(); + + /** {@return the constant double value} */ double doubleValue(); + + /** + * {@return the resolved double value} + * + * @implSpec + * This method returns the same as {@link #doubleValue()}. + */ + @Override + default Double resolvedValue() { + return doubleValue(); + } } /** - * Models a constant-valued element + * Models a float-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_FLOAT}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfFloat extends AnnotationValue.OfConstant + sealed interface OfFloat extends OfConstant permits AnnotationImpl.OfFloatImpl { - /** {@return the constant} */ + /** {@return the backing float entry} */ + @Override + FloatEntry constant(); + + /** {@return the constant float value} */ float floatValue(); + + /** + * {@return the resolved float value} + * + * @implSpec + * This method returns the same as {@link #floatValue()}. + */ + @Override + default Float resolvedValue() { + return floatValue(); + } } /** - * Models a constant-valued element + * Models a long-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_LONG}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfLong extends AnnotationValue.OfConstant + sealed interface OfLong extends OfConstant permits AnnotationImpl.OfLongImpl { - /** {@return the constant} */ + /** {@return the backing long entry} */ + @Override + LongEntry constant(); + + /** {@return the constant long value} */ long longValue(); + + /** + * {@return the resolved long value} + * + * @implSpec + * This method returns the same as {@link #longValue()}. + */ + @Override + default Long resolvedValue() { + return longValue(); + } } /** - * Models a constant-valued element + * Models an int-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_INT}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfInteger extends AnnotationValue.OfConstant - permits AnnotationImpl.OfIntegerImpl { - /** {@return the constant} */ + sealed interface OfInt extends OfConstant + permits AnnotationImpl.OfIntImpl { + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** {@return the constant int value} */ int intValue(); + + /** + * {@return the resolved int value} + * + * @implSpec + * This method returns the same as {@link #intValue()}. + */ + @Override + default Integer resolvedValue() { + return intValue(); + } } /** - * Models a constant-valued element + * Models a short-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_SHORT}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfShort extends AnnotationValue.OfConstant + sealed interface OfShort extends OfConstant permits AnnotationImpl.OfShortImpl { - /** {@return the constant} */ + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant short value} + * @jvms 2.11.1 Types and the Java Virtual Machine + */ short shortValue(); + + /** + * {@return the resolved short value} + * + * @implSpec + * This method returns the same as {@link #shortValue()}. + */ + @Override + default Short resolvedValue() { + return shortValue(); + } } /** - * Models a constant-valued element + * Models a char-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CHAR}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfCharacter extends AnnotationValue.OfConstant - permits AnnotationImpl.OfCharacterImpl { - /** {@return the constant} */ + sealed interface OfChar extends OfConstant + permits AnnotationImpl.OfCharImpl { + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant char value} + * @jvms 2.11.1 Types and the Java Virtual Machine + */ char charValue(); + + /** + * {@return the resolved char value} + * + * @implSpec + * This method returns the same as {@link #charValue()}. + */ + @Override + default Character resolvedValue() { + return charValue(); + } } /** - * Models a constant-valued element + * Models a byte-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BYTE}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfByte extends AnnotationValue.OfConstant + sealed interface OfByte extends OfConstant permits AnnotationImpl.OfByteImpl { - /** {@return the constant} */ + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant byte value} + * @jvms 2.11.1 Types and the Java Virtual Machine + */ byte byteValue(); + + /** + * {@return the resolved byte value} + * + * @implSpec + * This method returns the same as {@link #byteValue()}. + */ + @Override + default Byte resolvedValue() { + return byteValue(); + } } /** - * Models a constant-valued element + * Models a boolean-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_BOOLEAN}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) - sealed interface OfBoolean extends AnnotationValue.OfConstant + sealed interface OfBoolean extends OfConstant permits AnnotationImpl.OfBooleanImpl { - /** {@return the constant} */ + /** {@return the backing integer entry} */ + @Override + IntegerEntry constant(); + + /** + * {@return the constant boolean value} + * @jvms 2.3.4 The boolean Type + */ boolean booleanValue(); + + /** + * {@return the resolved boolean value} + * + * @implSpec + * This method returns the same as {@link #booleanValue()}. + */ + @Override + default Boolean resolvedValue() { + return booleanValue(); + } } /** - * Models a class-valued element + * Models a class-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_CLASS}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfClass extends AnnotationValue permits AnnotationImpl.OfClassImpl { - /** {@return the class name} */ + /** {@return the class descriptor string} */ Utf8Entry className(); - /** {@return the class symbol} */ + /** {@return the class descriptor} */ default ClassDesc classSymbol() { return ClassDesc.ofDescriptor(className().stringValue()); } } /** - * Models an enum-valued element + * Models an enum-valued element. + * The {@linkplain #tag tag} of this element is {@value ClassFile#AEV_ENUM}. * * @since 22 */ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API) sealed interface OfEnum extends AnnotationValue permits AnnotationImpl.OfEnumImpl { - /** {@return the enum class name} */ + /** {@return the enum class descriptor string} */ Utf8Entry className(); - /** {@return the enum class symbol} */ + /** {@return the enum class descriptor} */ default ClassDesc classSymbol() { return ClassDesc.ofDescriptor(className().stringValue()); } @@ -249,7 +432,7 @@ default ClassDesc classSymbol() { /** * {@return an annotation element for a enum-valued element} - * @param className the name of the enum class + * @param className the descriptor string of the enum class * @param constantName the name of the enum constant */ static OfEnum ofEnum(Utf8Entry className, @@ -259,7 +442,7 @@ static OfEnum ofEnum(Utf8Entry className, /** * {@return an annotation element for a enum-valued element} - * @param className the name of the enum class + * @param className the descriptor of the enum class * @param constantName the name of the enum constant */ static OfEnum ofEnum(ClassDesc className, String constantName) { @@ -269,7 +452,7 @@ static OfEnum ofEnum(ClassDesc className, String constantName) { /** * {@return an annotation element for a class-valued element} - * @param className the name of the enum class + * @param className the descriptor string of the class */ static OfClass ofClass(Utf8Entry className) { return new AnnotationImpl.OfClassImpl(className); @@ -277,7 +460,7 @@ static OfClass ofClass(Utf8Entry className) { /** * {@return an annotation element for a class-valued element} - * @param className the name of the enum class + * @param className the descriptor of the class */ static OfClass ofClass(ClassDesc className) { return ofClass(TemporaryConstantPool.INSTANCE.utf8Entry(className.descriptorString())); @@ -287,7 +470,7 @@ static OfClass ofClass(ClassDesc className) { * {@return an annotation element for a string-valued element} * @param value the string */ - static OfConstant ofString(Utf8Entry value) { + static OfString ofString(Utf8Entry value) { return new AnnotationImpl.OfStringImpl(value); } @@ -295,7 +478,7 @@ static OfConstant ofString(Utf8Entry value) { * {@return an annotation element for a string-valued element} * @param value the string */ - static OfConstant ofString(String value) { + static OfString ofString(String value) { return ofString(TemporaryConstantPool.INSTANCE.utf8Entry(value)); } @@ -303,7 +486,7 @@ static OfConstant ofString(String value) { * {@return an annotation element for a double-valued element} * @param value the double value */ - static OfConstant ofDouble(DoubleEntry value) { + static OfDouble ofDouble(DoubleEntry value) { return new AnnotationImpl.OfDoubleImpl(value); } @@ -311,7 +494,7 @@ static OfConstant ofDouble(DoubleEntry value) { * {@return an annotation element for a double-valued element} * @param value the double value */ - static OfConstant ofDouble(double value) { + static OfDouble ofDouble(double value) { return ofDouble(TemporaryConstantPool.INSTANCE.doubleEntry(value)); } @@ -319,7 +502,7 @@ static OfConstant ofDouble(double value) { * {@return an annotation element for a float-valued element} * @param value the float value */ - static OfConstant ofFloat(FloatEntry value) { + static OfFloat ofFloat(FloatEntry value) { return new AnnotationImpl.OfFloatImpl(value); } @@ -327,7 +510,7 @@ static OfConstant ofFloat(FloatEntry value) { * {@return an annotation element for a float-valued element} * @param value the float value */ - static OfConstant ofFloat(float value) { + static OfFloat ofFloat(float value) { return ofFloat(TemporaryConstantPool.INSTANCE.floatEntry(value)); } @@ -335,7 +518,7 @@ static OfConstant ofFloat(float value) { * {@return an annotation element for a long-valued element} * @param value the long value */ - static OfConstant ofLong(LongEntry value) { + static OfLong ofLong(LongEntry value) { return new AnnotationImpl.OfLongImpl(value); } @@ -343,7 +526,7 @@ static OfConstant ofLong(LongEntry value) { * {@return an annotation element for a long-valued element} * @param value the long value */ - static OfConstant ofLong(long value) { + static OfLong ofLong(long value) { return ofLong(TemporaryConstantPool.INSTANCE.longEntry(value)); } @@ -351,15 +534,15 @@ static OfConstant ofLong(long value) { * {@return an annotation element for an int-valued element} * @param value the int value */ - static OfConstant ofInt(IntegerEntry value) { - return new AnnotationImpl.OfIntegerImpl(value); + static OfInt ofInt(IntegerEntry value) { + return new AnnotationImpl.OfIntImpl(value); } /** * {@return an annotation element for an int-valued element} * @param value the int value */ - static OfConstant ofInt(int value) { + static OfInt ofInt(int value) { return ofInt(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -367,7 +550,7 @@ static OfConstant ofInt(int value) { * {@return an annotation element for a short-valued element} * @param value the short value */ - static OfConstant ofShort(IntegerEntry value) { + static OfShort ofShort(IntegerEntry value) { return new AnnotationImpl.OfShortImpl(value); } @@ -375,7 +558,7 @@ static OfConstant ofShort(IntegerEntry value) { * {@return an annotation element for a short-valued element} * @param value the short value */ - static OfConstant ofShort(short value) { + static OfShort ofShort(short value) { return ofShort(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -383,15 +566,15 @@ static OfConstant ofShort(short value) { * {@return an annotation element for a char-valued element} * @param value the char value */ - static OfConstant ofChar(IntegerEntry value) { - return new AnnotationImpl.OfCharacterImpl(value); + static OfChar ofChar(IntegerEntry value) { + return new AnnotationImpl.OfCharImpl(value); } /** * {@return an annotation element for a char-valued element} * @param value the char value */ - static OfConstant ofChar(char value) { + static OfChar ofChar(char value) { return ofChar(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -399,7 +582,7 @@ static OfConstant ofChar(char value) { * {@return an annotation element for a byte-valued element} * @param value the byte value */ - static OfConstant ofByte(IntegerEntry value) { + static OfByte ofByte(IntegerEntry value) { return new AnnotationImpl.OfByteImpl(value); } @@ -407,7 +590,7 @@ static OfConstant ofByte(IntegerEntry value) { * {@return an annotation element for a byte-valued element} * @param value the byte value */ - static OfConstant ofByte(byte value) { + static OfByte ofByte(byte value) { return ofByte(TemporaryConstantPool.INSTANCE.intEntry(value)); } @@ -415,7 +598,7 @@ static OfConstant ofByte(byte value) { * {@return an annotation element for a boolean-valued element} * @param value the boolean value */ - static OfConstant ofBoolean(IntegerEntry value) { + static OfBoolean ofBoolean(IntegerEntry value) { return new AnnotationImpl.OfBooleanImpl(value); } @@ -423,7 +606,7 @@ static OfConstant ofBoolean(IntegerEntry value) { * {@return an annotation element for a boolean-valued element} * @param value the boolean value */ - static OfConstant ofBoolean(boolean value) { + static OfBoolean ofBoolean(boolean value) { int i = value ? 1 : 0; return ofBoolean(TemporaryConstantPool.INSTANCE.intEntry(i)); } @@ -438,7 +621,7 @@ static OfAnnotation ofAnnotation(Annotation value) { /** * {@return an annotation element for an array-valued element} - * @param values the values + * @param values the array elements */ static OfArray ofArray(List values) { return new AnnotationImpl.OfArrayImpl(values); @@ -446,7 +629,7 @@ static OfArray ofArray(List values) { /** * {@return an annotation element for an array-valued element} - * @param values the values + * @param values the array elements */ static OfArray ofArray(AnnotationValue... values) { return ofArray(List.of(values)); diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java index 3a7053a49f5..d405f68570e 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/AnnotationConstantValueEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,13 +24,23 @@ */ package java.lang.classfile.constantpool; +import java.lang.classfile.AnnotationValue; import java.lang.constant.ConstantDesc; import jdk.internal.javac.PreviewFeature; /** - * A constant pool entry that may be used as an annotation constant, - * which includes the four kinds of primitive constants, and UTF8 constants. + * A constant pool entry that may be used by annotation constant values, + * which includes the four kinds of primitive constants and UTF8 constants. + * These entries are also the only entries that do not refer to other + * constant pool entries. * + * @apiNote + * An annotation constant value entry alone is not sufficient to determine + * the annotation constant; for example, an {@link IntegerEntry} of {@code 1} + * can mean {@code true} in {@link AnnotationValue.OfBoolean} or {@code 1} + * in {@link AnnotationValue.OfInt}. + * + * @see AnnotationValue.OfConstant * @sealedGraph * @since 22 */ @@ -40,7 +50,8 @@ public sealed interface AnnotationConstantValueEntry extends PoolEntry /** * {@return the constant value} The constant value will be an {@link Integer}, - * {@link Long}, {@link Float}, {@link Double}, or {@link String}. + * {@link Long}, {@link Float}, {@link Double} for the primitive constants, + * or {@link String} for UTF8 constants. */ ConstantDesc constantValue(); } diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java index c0927175476..db77f8e2e8a 100644 --- a/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java @@ -510,25 +510,6 @@ default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) { throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass())); } - /** - * {@return An {@link AnnotationConstantValueEntry} describing the provided - * constant} The constant should be an Integer, String, Long, Float, - * Double, ClassDesc (for a Class constant), or MethodTypeDesc (for a MethodType - * constant.) - * - * @param c the constant - */ - default AnnotationConstantValueEntry annotationConstantValueEntry(ConstantDesc c) { - if (c instanceof Integer i) return intEntry(i); - if (c instanceof String s) return utf8Entry(s); - if (c instanceof Long l) return longEntry(l); - if (c instanceof Float f) return floatEntry(f); - if (c instanceof Double d) return doubleEntry(d); - if (c instanceof ClassDesc cd) return utf8Entry(cd); - if (c instanceof MethodTypeDesc mtd) return utf8Entry(mtd); - throw new IllegalArgumentException("Illegal type: " + (c == null ? null : c.getClass())); - } - /** * {@return a {@link BootstrapMethodEntry} describing the provided * bootstrap method and static arguments} diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java index 03353e272a6..794e7915960 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationImpl.java @@ -27,7 +27,6 @@ import java.lang.classfile.*; import java.lang.classfile.constantpool.*; -import java.lang.constant.ConstantDesc; import java.util.List; import static java.lang.classfile.ClassFile.*; @@ -80,12 +79,7 @@ public void writeTo(BufWriterImpl buf) { } } - public sealed interface OfConstantImpl extends AnnotationValue.OfConstant, Util.Writable - permits AnnotationImpl.OfStringImpl, AnnotationImpl.OfDoubleImpl, - AnnotationImpl.OfFloatImpl, AnnotationImpl.OfLongImpl, - AnnotationImpl.OfIntegerImpl, AnnotationImpl.OfShortImpl, - AnnotationImpl.OfCharacterImpl, AnnotationImpl.OfByteImpl, - AnnotationImpl.OfBooleanImpl { + public sealed interface OfConstantImpl extends AnnotationValue.OfConstant, Util.Writable { @Override default void writeTo(BufWriterImpl buf) { @@ -93,15 +87,10 @@ default void writeTo(BufWriterImpl buf) { buf.writeIndex(constant()); } - @Override - default ConstantDesc constantValue() { - return constant().constantValue(); - } - } public record OfStringImpl(Utf8Entry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfString { + implements OfConstantImpl, AnnotationValue.OfString { @Override public char tag() { @@ -115,7 +104,7 @@ public String stringValue() { } public record OfDoubleImpl(DoubleEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfDouble { + implements OfConstantImpl, AnnotationValue.OfDouble { @Override public char tag() { @@ -129,7 +118,7 @@ public double doubleValue() { } public record OfFloatImpl(FloatEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfFloat { + implements OfConstantImpl, AnnotationValue.OfFloat { @Override public char tag() { @@ -143,7 +132,7 @@ public float floatValue() { } public record OfLongImpl(LongEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfLong { + implements OfConstantImpl, AnnotationValue.OfLong { @Override public char tag() { @@ -156,8 +145,8 @@ public long longValue() { } } - public record OfIntegerImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfInteger { + public record OfIntImpl(IntegerEntry constant) + implements OfConstantImpl, AnnotationValue.OfInt { @Override public char tag() { @@ -171,7 +160,7 @@ public int intValue() { } public record OfShortImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfShort { + implements OfConstantImpl, AnnotationValue.OfShort { @Override public char tag() { @@ -180,12 +169,12 @@ public char tag() { @Override public short shortValue() { - return (short)constant().intValue(); + return (short) constant().intValue(); } } - public record OfCharacterImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfCharacter { + public record OfCharImpl(IntegerEntry constant) + implements OfConstantImpl, AnnotationValue.OfChar { @Override public char tag() { @@ -194,12 +183,12 @@ public char tag() { @Override public char charValue() { - return (char)constant().intValue(); + return (char) constant().intValue(); } } public record OfByteImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfByte { + implements OfConstantImpl, AnnotationValue.OfByte { @Override public char tag() { @@ -208,12 +197,12 @@ public char tag() { @Override public byte byteValue() { - return (byte)constant().intValue(); + return (byte) constant().intValue(); } } public record OfBooleanImpl(IntegerEntry constant) - implements AnnotationImpl.OfConstantImpl, AnnotationValue.OfBoolean { + implements OfConstantImpl, AnnotationValue.OfBoolean { @Override public char tag() { @@ -222,15 +211,15 @@ public char tag() { @Override public boolean booleanValue() { - return constant().intValue() == 1; + return constant().intValue() != 0; } } public record OfArrayImpl(List values) implements AnnotationValue.OfArray, Util.Writable { - public OfArrayImpl(List values) { - this.values = List.copyOf(values); + public OfArrayImpl { + values = List.copyOf(values); } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java index 2ada13aaba8..e21938bbc0c 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java @@ -60,10 +60,10 @@ public static AnnotationValue readElementValue(ClassReader classReader, int p) { ++p; return switch (tag) { case AEV_BYTE -> new AnnotationImpl.OfByteImpl(classReader.readEntry(p, IntegerEntry.class)); - case AEV_CHAR -> new AnnotationImpl.OfCharacterImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_CHAR -> new AnnotationImpl.OfCharImpl(classReader.readEntry(p, IntegerEntry.class)); case AEV_DOUBLE -> new AnnotationImpl.OfDoubleImpl(classReader.readEntry(p, DoubleEntry.class)); case AEV_FLOAT -> new AnnotationImpl.OfFloatImpl(classReader.readEntry(p, FloatEntry.class)); - case AEV_INT -> new AnnotationImpl.OfIntegerImpl(classReader.readEntry(p, IntegerEntry.class)); + case AEV_INT -> new AnnotationImpl.OfIntImpl(classReader.readEntry(p, IntegerEntry.class)); case AEV_LONG -> new AnnotationImpl.OfLongImpl(classReader.readEntry(p, LongEntry.class)); case AEV_SHORT -> new AnnotationImpl.OfShortImpl(classReader.readEntry(p, IntegerEntry.class)); case AEV_BOOLEAN -> new AnnotationImpl.OfBooleanImpl(classReader.readEntry(p, IntegerEntry.class)); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java index fac2eba95fe..75346dd5998 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -507,15 +507,15 @@ private static String toXmlName(String name) { private static Node[] elementValueToTree(AnnotationValue v) { return switch (v) { - case OfString cv -> leafs("string", String.valueOf(cv.constantValue())); - case OfDouble cv -> leafs("double", String.valueOf(cv.constantValue())); - case OfFloat cv -> leafs("float", String.valueOf(cv.constantValue())); - case OfLong cv -> leafs("long", String.valueOf(cv.constantValue())); - case OfInteger cv -> leafs("int", String.valueOf(cv.constantValue())); - case OfShort cv -> leafs("short", String.valueOf(cv.constantValue())); - case OfCharacter cv -> leafs("char", String.valueOf(cv.constantValue())); - case OfByte cv -> leafs("byte", String.valueOf(cv.constantValue())); - case OfBoolean cv -> leafs("boolean", String.valueOf((int)cv.constantValue() != 0)); + case OfString cv -> leafs("string", String.valueOf(cv.stringValue())); + case OfDouble cv -> leafs("double", String.valueOf(cv.doubleValue())); + case OfFloat cv -> leafs("float", String.valueOf(cv.floatValue())); + case OfLong cv -> leafs("long", String.valueOf(cv.longValue())); + case OfInt cv -> leafs("int", String.valueOf(cv.intValue())); + case OfShort cv -> leafs("short", String.valueOf(cv.shortValue())); + case OfChar cv -> leafs("char", String.valueOf(cv.charValue())); + case OfByte cv -> leafs("byte", String.valueOf(cv.byteValue())); + case OfBoolean cv -> leafs("boolean", String.valueOf(cv.booleanValue())); case OfClass clv -> leafs("class", clv.className().stringValue()); case OfEnum ev -> leafs("enum class", ev.className().stringValue(), "constant name", ev.constantName().stringValue()); diff --git a/test/jdk/jdk/classfile/AnnotationTest.java b/test/jdk/jdk/classfile/AnnotationTest.java index 4ed3b2141ad..6b6b88b3de1 100644 --- a/test/jdk/jdk/classfile/AnnotationTest.java +++ b/test/jdk/jdk/classfile/AnnotationTest.java @@ -28,6 +28,8 @@ */ import java.lang.constant.ClassDesc; import static java.lang.constant.ConstantDescs.*; + +import java.lang.constant.ConstantDesc; import java.lang.constant.MethodTypeDesc; import java.util.AbstractMap; import java.util.ArrayList; @@ -39,6 +41,8 @@ import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; import java.lang.classfile.*; import java.lang.classfile.constantpool.ConstantPoolBuilder; +import java.util.stream.Stream; + import org.junit.jupiter.api.Test; import static java.util.stream.Collectors.toList; @@ -53,26 +57,30 @@ class AnnotationTest { enum E {C}; - private static Map constants + // name -> (value, poolValue) + private static final Map> constants = Map.ofEntries( - new AbstractMap.SimpleImmutableEntry<>("i", 1), - new AbstractMap.SimpleImmutableEntry<>("j", 1L), - new AbstractMap.SimpleImmutableEntry<>("s", 1), - new AbstractMap.SimpleImmutableEntry<>("b", 1), - new AbstractMap.SimpleImmutableEntry<>("f", 1.0f), - new AbstractMap.SimpleImmutableEntry<>("d", 1.0d), - new AbstractMap.SimpleImmutableEntry<>("z", 1), - new AbstractMap.SimpleImmutableEntry<>("c", (int) '1'), - new AbstractMap.SimpleImmutableEntry<>("st", "1"), - new AbstractMap.SimpleImmutableEntry<>("cl", ClassDesc.of("foo.Bar")), - new AbstractMap.SimpleImmutableEntry<>("en", E.C), - new AbstractMap.SimpleImmutableEntry<>("arr", new Object[] {1, "1", 1.0f}) + Map.entry("i", Map.entry(1, 1)), + Map.entry("j", Map.entry(1L, 1L)), + Map.entry("s", Map.entry((short) 1, 1)), + Map.entry("b", Map.entry((byte) 1, 1)), + Map.entry("f", Map.entry(1.0f, 1.0f)), + Map.entry("d", Map.entry(1.0d, 1.0d)), + Map.entry("z", Map.entry(true, 1)), + Map.entry("c", Map.entry('1', (int) '1')), + Map.entry("st", Map.entry("1", "1")) ); - private static final List constantElements = + private static final List constantElements = Stream.concat( constants.entrySet().stream() - .map(e -> AnnotationElement.of(e.getKey(), AnnotationValue.of(e.getValue()))) - .toList(); + .map(e -> Map.entry(e.getKey(), e.getValue().getKey())), + Stream.of( + Map.entry("cl", ClassDesc.of("foo.Bar")), + Map.entry("en", E.C), + Map.entry("arr", new Object[] {1, "1", 1.0f}) + )) + .map(e -> AnnotationElement.of(e.getKey(), AnnotationValue.of(e.getValue()))) + .toList(); private static List elements() { List list = new ArrayList<>(constantElements); @@ -88,9 +96,12 @@ private static boolean assertAnno(Annotation a, String annoClassDescriptor, bool names.add(evp.name().stringValue()); switch (evp.name().stringValue()) { case "i", "j", "s", "b", "f", "d", "z", "c", "st": - assertTrue (evp.value() instanceof AnnotationValue.OfConstant c); - assertEquals(((AnnotationValue.OfConstant) evp.value()).constantValue(), - constants.get(evp.name().stringValue())); + if (!(evp.value() instanceof AnnotationValue.OfConstant c)) + return fail(); + assertEquals(c.resolvedValue(), + constants.get(evp.name().stringValue()).getKey()); + assertEquals(c.constant().constantValue(), + constants.get(evp.name().stringValue()).getValue()); break; case "cl": assertTrue (evp.value() instanceof AnnotationValue.OfClass c @@ -105,8 +116,9 @@ private static boolean assertAnno(Annotation a, String annoClassDescriptor, bool && assertAnno(c.annotation(), "LBar;", false)); break; case "arr": - assertTrue (evp.value() instanceof AnnotationValue.OfArray); - List values = ((AnnotationValue.OfArray) evp.value()).values(); + if (!(evp.value() instanceof AnnotationValue.OfArray arr)) + return fail(); + List values = arr.values(); assertEquals(values.stream().map(v -> ((AnnotationValue.OfConstant) v).constant().constantValue()).collect(toSet()), Set.of(1, 1.0f, "1")); break; diff --git a/test/jdk/jdk/classfile/ClassPrinterTest.java b/test/jdk/jdk/classfile/ClassPrinterTest.java index 9c25ff7e13a..7668648f829 100644 --- a/test/jdk/jdk/classfile/ClassPrinterTest.java +++ b/test/jdk/jdk/classfile/ClassPrinterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 8335927 * @summary Testing ClassFile ClassPrinter. * @run junit ClassPrinterTest */ @@ -249,7 +250,7 @@ record components: flags: [PROTECTED] method type: (ZLjava/lang/Throwable;)Ljava/lang/Void; attributes: [AnnotationDefault, RuntimeVisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations, Exceptions, Code] - annotation default: {array: [{boolean: true}, {byte: 12}, {char: 99}, {class: LPhee;}, {double: 1.3}, {enum class: LBoo;, constant name: BOO}, {float: 3.7}, {int: 33}, {long: 3333}, {short: 25}, {string: BOO}, {annotation class: LPhoo;}]} + annotation default: {array: [{boolean: true}, {byte: 12}, {char: c}, {class: LPhee;}, {double: 1.3}, {enum class: LBoo;, constant name: BOO}, {float: 3.7}, {int: 33}, {long: 3333}, {short: 25}, {string: BOO}, {annotation class: LPhoo;}]} visible parameter annotations: parameter 1: [{annotation class: LPhoo;, values: [{name: flfl, value: {float: 22.0}}, {name: frfl, value: {float: 11.0}}]}] invisible parameter annotations: @@ -500,7 +501,7 @@ void testPrintJsonTraceAll() throws IOException { "flags": ["PROTECTED"], "method type": "(ZLjava/lang/Throwable;)Ljava/lang/Void;", "attributes": ["AnnotationDefault", "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", "Exceptions", "Code"], - "annotation default": {"array": [{"boolean": "true"}, {"byte": "12"}, {"char": "99"}, {"class": "LPhee;"}, {"double": "1.3"}, {"enum class": "LBoo;", "constant name": "BOO"}, {"float": "3.7"}, {"int": "33"}, {"long": "3333"}, {"short": "25"}, {"string": "BOO"}, {"annotation class": "LPhoo;"}]}, + "annotation default": {"array": [{"boolean": "true"}, {"byte": "12"}, {"char": "c"}, {"class": "LPhee;"}, {"double": "1.3"}, {"enum class": "LBoo;", "constant name": "BOO"}, {"float": "3.7"}, {"int": "33"}, {"long": "3333"}, {"short": "25"}, {"string": "BOO"}, {"annotation class": "LPhoo;"}]}, "visible parameter annotations": { "parameter 1": [{"annotation class": "LPhoo;", "values": [{"name": "flfl", "value": {"float": "22.0"}}, {"name": "frfl", "value": {"float": "11.0"}}]}]}, "invisible parameter annotations": { @@ -756,7 +757,7 @@ void testPrintXmlTraceAll() throws IOException { PROTECTED (ZLjava/lang/Throwable;)Ljava/lang/Void; AnnotationDefaultRuntimeVisibleParameterAnnotationsRuntimeInvisibleParameterAnnotationsExceptionsCode - true1299LPhee;1.3LBoo;BOO3.733333325BOOLPhoo; + true12cLPhee;1.3LBoo;BOO3.733333325BOOLPhoo; LPhoo;flfl22.0frfl11.0 @@ -907,6 +908,6 @@ private static void assertOut(StringBuilder out, String expected) { // System.out.println("-----------------"); // System.out.println(out.toString()); // System.out.println("-----------------"); - assertArrayEquals(out.toString().trim().split(" *\r?\n"), expected.trim().split("\n")); + assertArrayEquals(expected.trim().split("\n"), out.toString().trim().split(" *\r?\n")); } } diff --git a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java index 2af3cd9410f..7667403aaab 100644 --- a/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java +++ b/test/jdk/jdk/classfile/helpers/RebuildingTransformation.java @@ -165,9 +165,9 @@ static AnnotationValue transformAnnotationValue(AnnotationValue av) { case AnnotationValue.OfDouble v -> AnnotationValue.of(v.doubleValue()); case AnnotationValue.OfFloat v -> AnnotationValue.of(v.floatValue()); case AnnotationValue.OfLong v -> AnnotationValue.of(v.longValue()); - case AnnotationValue.OfInteger v -> AnnotationValue.of(v.intValue()); + case AnnotationValue.OfInt v -> AnnotationValue.of(v.intValue()); case AnnotationValue.OfShort v -> AnnotationValue.of(v.shortValue()); - case AnnotationValue.OfCharacter v -> AnnotationValue.of(v.charValue()); + case AnnotationValue.OfChar v -> AnnotationValue.of(v.charValue()); case AnnotationValue.OfByte v -> AnnotationValue.of(v.byteValue()); case AnnotationValue.OfBoolean v -> AnnotationValue.of(v.booleanValue()); case AnnotationValue.OfClass oc -> AnnotationValue.of(oc.classSymbol()); diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java index 64c33ed9fd9..94610ddf055 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnonymousClassTest.java @@ -246,7 +246,7 @@ private static String annotationValueDebugString(ClassModel cm, Annotation annot private static String elementValueDebugString(AnnotationValue value) { if (value.tag() == 'I') { - return Integer.toString(((AnnotationValue.OfInteger) value).intValue()); + return Integer.toString(((AnnotationValue.OfInt) value).intValue()); } else { throw new UnsupportedOperationException(String.format("%c", value.tag())); } diff --git a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java index d85b37aa3a3..8efb13ccbdf 100644 --- a/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java +++ b/test/langtools/tools/javac/classfiles/attributes/AnnotationDefault/AnnotationDefaultVerifier.java @@ -103,7 +103,7 @@ public void testElementValue( case AnnotationValue.OfByte ev -> { testCase.checkEquals((int)ev.byteValue(), Integer.parseInt(values[0]), "const_value_index"); } - case AnnotationValue.OfCharacter ev -> { + case AnnotationValue.OfChar ev -> { testCase.checkEquals((int)ev.charValue(), Integer.parseInt(values[0]), "const_value_index"); } case AnnotationValue.OfShort ev -> { @@ -113,7 +113,7 @@ public void testElementValue( testCase.checkEquals(ev.booleanValue()? 1: 0, Integer.parseInt(values[0]), "const_value_index"); } default -> { - testCase.checkEquals(((AnnotationValue.OfInteger) element_value).intValue(), Integer.parseInt(values[0]), "const_value_index"); + testCase.checkEquals(((AnnotationValue.OfInt) element_value).intValue(), Integer.parseInt(values[0]), "const_value_index"); } } } diff --git a/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java b/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java index 5bf587d1b8b..3f422b541c0 100644 --- a/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java +++ b/test/langtools/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,7 +123,7 @@ public void testElementValue(TestResult testResult, testResult.checkEquals((int)((AnnotationValue.OfShort) element_value).shortValue(), value, "const_value_index : " + value); break; default: - testResult.checkEquals(((AnnotationValue.OfInteger) element_value).intValue(), value, "const_value_index : " + value); + testResult.checkEquals(((AnnotationValue.OfInt) element_value).intValue(), value, "const_value_index : " + value); } } @@ -169,8 +169,8 @@ public void testElementValue(TestResult testResult, ClassModel classFile, AnnotationValue element_value) { testTag(testResult, element_value.tag()); - AnnotationValue.OfCharacter ev = - (AnnotationValue.OfCharacter) element_value; + AnnotationValue.OfChar ev = + (AnnotationValue.OfChar) element_value; testResult.checkEquals(ev.charValue(), value, "const_value_index : " + value); } From 58b957054437edee7d0abc365133985ac30a6af4 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 13 Aug 2024 16:05:38 +0000 Subject: [PATCH 62/84] 8338142: (dc) DatagramChannelImpl.blockingReceive can use untimed-park when no timeout set Reviewed-by: dfuchs --- .../classes/sun/nio/ch/DatagramChannelImpl.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 5c06ac7d9be..06e79f416ac 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -674,7 +674,6 @@ void blockingReceive(DatagramPacket p, long nanos) throws IOException { configureSocketNonBlocking(); } else { configureSocketNonBlockingIfVirtualThread(); - nanos = Long.MAX_VALUE; } // p.bufLength is the maximum size of the datagram that can be received @@ -689,7 +688,9 @@ void blockingReceive(DatagramPacket p, long nanos) throws IOException { SocketAddress remote = beginRead(true, false); boolean connected = (remote != null); do { - long remainingNanos = nanos - (System.nanoTime() - startNanos); + long remainingNanos = (nanos > 0) + ? nanos - (System.nanoTime() - startNanos) + : 0; ByteBuffer dst = tryBlockingReceive(connected, bufLength, remainingNanos); // if datagram received then get sender and copy to DatagramPacket @@ -756,11 +757,15 @@ private ByteBuffer tryBlockingReceive(boolean connected, int len, long nanos) Util.offerFirstTemporaryDirectBuffer(dst); dst = null; } - long remainingNanos = nanos - (System.nanoTime() - startNanos); - if (remainingNanos <= 0) { - throw new SocketTimeoutException("Receive timed out"); + if (nanos > 0) { + long remainingNanos = nanos - (System.nanoTime() - startNanos); + if (remainingNanos <= 0) { + throw new SocketTimeoutException("Receive timed out"); + } + park(Net.POLLIN, remainingNanos); + } else { + park(Net.POLLIN); } - park(Net.POLLIN, remainingNanos); // virtual thread needs to re-allocate temporary direct buffer after parking if (Thread.currentThread().isVirtual()) { dst = Util.getTemporaryDirectBuffer(len); From 21ca91e55dd83dc011e67a2d056e3e3bd44d40b5 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Tue, 13 Aug 2024 16:25:43 +0000 Subject: [PATCH 63/84] 8300800: UB: Shift exponent 32 is too large for 32-bit type 'int' Reviewed-by: kbarrett, adinn, gziemski --- src/hotspot/cpu/aarch64/immediate_aarch64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp index 7caafc19fbd..9c67a0dfead 100644 --- a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp @@ -295,7 +295,7 @@ static int expandLogicalImmediate(uint32_t immN, uint32_t immr, uint64_t and_bits_sub = replicate(and_bit, 1, nbits); uint64_t or_bits_sub = replicate(or_bit, 1, nbits); uint64_t and_bits_top = (and_bits_sub << nbits) | ones(nbits); - uint64_t or_bits_top = (0 << nbits) | or_bits_sub; + uint64_t or_bits_top = (UCONST64(0) << nbits) | or_bits_sub; tmask = ((tmask & (replicate(and_bits_top, 2 * nbits, 32 / nbits))) From 84c3065e8004122f3455a8c28c8719b2c8111c17 Mon Sep 17 00:00:00 2001 From: Neethu Prasad Date: Tue, 13 Aug 2024 17:22:41 +0000 Subject: [PATCH 64/84] 8335865: Shenandoah: Improve THP pretouch after JDK-8315923 Reviewed-by: shade, wkemper --- .../share/gc/shenandoah/shenandoahHeap.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 0a20307abcb..7904cd5f1cd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -283,14 +283,7 @@ jint ShenandoahHeap::initialize() { // Reserve aux bitmap for use in object_iterate(). We don't commit it here. size_t aux_bitmap_page_size = bitmap_page_size; -#ifdef LINUX - // In THP "advise" mode, we refrain from advising the system to use large pages - // since we know these commits will be short lived, and there is no reason to trash - // the THP area with this bitmap. - if (UseTransparentHugePages) { - aux_bitmap_page_size = os::vm_page_size(); - } -#endif + ReservedSpace aux_bitmap(_bitmap_size, aux_bitmap_page_size); os::trace_page_sizes_for_requested_size("Aux Bitmap", bitmap_size_orig, aux_bitmap_page_size, @@ -387,16 +380,6 @@ jint ShenandoahHeap::initialize() { _pretouch_heap_page_size = heap_page_size; _pretouch_bitmap_page_size = bitmap_page_size; -#ifdef LINUX - // UseTransparentHugePages would madvise that backing memory can be coalesced into huge - // pages. But, the kernel needs to know that every small page is used, in order to coalesce - // them into huge one. Therefore, we need to pretouch with smaller pages. - if (UseTransparentHugePages) { - _pretouch_heap_page_size = (size_t)os::vm_page_size(); - _pretouch_bitmap_page_size = (size_t)os::vm_page_size(); - } -#endif - // OS memory managers may want to coalesce back-to-back pages. Make their jobs // simpler by pre-touching continuous spaces (heap and bitmap) separately. From ca99f37f82bf59fc720babbc155502ef92d34de6 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 13 Aug 2024 18:02:24 +0000 Subject: [PATCH 65/84] 8338156: Fix -Wzero-as-null-pointer-constant warnings in jvmciCompilerToVM.cpp Reviewed-by: tschatzl, jwaters, dnsimon --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 5a9b18fc4d3..af72322ff4b 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -549,8 +549,8 @@ C2V_END C2V_VMENTRY_NULL(jobject, getImplementor, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (!klass->is_interface()) { - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - err_msg("Expected interface type, got %s", klass->external_name())); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("Expected interface type, got %s", klass->external_name())); } InstanceKlass* iklass = InstanceKlass::cast(klass); JVMCIKlassHandle handle(THREAD, iklass->implementor()); @@ -589,7 +589,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU TempNewSymbol class_name = SymbolTable::new_symbol(str); if (class_name->utf8_length() <= 1) { - JVMCI_THROW_MSG_0(InternalError, err_msg("Primitive type %s should be handled in Java code", str)); + JVMCI_THROW_MSG_NULL(InternalError, err_msg("Primitive type %s should be handled in Java code", str)); } #ifdef ASSERT @@ -598,8 +598,8 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU if (strstr(val, "") != nullptr) { tty->print_cr("CompilerToVM.lookupType: %s", str); } else if (strstr(str, val) != nullptr) { - THROW_MSG_0(vmSymbols::java_lang_Exception(), - err_msg("lookupTypeException: %s", str)); + THROW_MSG_NULL(vmSymbols::java_lang_Exception(), + err_msg("lookupTypeException: %s", str)); } } #endif @@ -617,7 +617,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU case 1: class_loader = Handle(THREAD, SystemDictionary::java_platform_loader()); break; case 2: class_loader = Handle(THREAD, SystemDictionary::java_system_loader()); break; default: - JVMCI_THROW_MSG_0(InternalError, err_msg("Illegal class loader value: %d", accessing_klass_loader)); + JVMCI_THROW_MSG_NULL(InternalError, err_msg("Illegal class loader value: %d", accessing_klass_loader)); } JVMCIENV->runtime()->initialize(JVMCI_CHECK_NULL); } @@ -660,7 +660,7 @@ C2V_VMENTRY_NULL(jobject, getArrayType, (JNIEnv* env, jobject, jchar type_char, JVMCIKlassHandle array_klass(THREAD); Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { - BasicType type = JVMCIENV->typeCharToBasicType(type_char, JVMCI_CHECK_0); + BasicType type = JVMCIENV->typeCharToBasicType(type_char, JVMCI_CHECK_NULL); if (type == T_VOID) { return nullptr; } @@ -812,7 +812,7 @@ C2V_VMENTRY_NULL(jobjectArray, resolveBootstrapMethod, (JNIEnv* env, jobject, AR bool is_indy = tag.is_invoke_dynamic(); bool is_condy = tag.is_dynamic_constant(); if (!(is_condy || is_indy)) { - JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Unexpected constant pool tag at index %d: %d", index, tag.value())); + JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Unexpected constant pool tag at index %d: %d", index, tag.value())); } // Get the indy entry based on CP index int indy_index = -1; @@ -1969,11 +1969,11 @@ C2V_END C2V_VMENTRY_NULL(jobject, getInterfaces, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } if (!klass->is_instance_klass()) { - JVMCI_THROW_MSG_0(InternalError, err_msg("Class %s must be instance klass", klass->external_name())); + JVMCI_THROW_MSG_NULL(InternalError, err_msg("Class %s must be instance klass", klass->external_name())); } InstanceKlass* iklass = InstanceKlass::cast(klass); @@ -1993,7 +1993,7 @@ C2V_END C2V_VMENTRY_NULL(jobject, getComponentType, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } if (!klass->is_array_klass()) { @@ -2002,8 +2002,8 @@ C2V_VMENTRY_NULL(jobject, getComponentType, (JNIEnv* env, jobject, ARGUMENT_PAIR oop mirror = klass->java_mirror(); oop component_mirror = java_lang_Class::component_mirror(mirror); if (component_mirror == nullptr) { - JVMCI_THROW_MSG_0(NullPointerException, - err_msg("Component mirror for array class %s is null", klass->external_name())) + JVMCI_THROW_MSG_NULL(NullPointerException, + err_msg("Component mirror for array class %s is null", klass->external_name())) } Klass* component_klass = java_lang_Class::as_Klass(component_mirror); @@ -2106,7 +2106,7 @@ C2V_END C2V_VMENTRY_NULL(jobject, unboxPrimitive, (JNIEnv* env, jobject, jobject object)) if (object == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } Handle box = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL); BasicType type = java_lang_boxing_object::basic_type(box()); @@ -2120,7 +2120,7 @@ C2V_END C2V_VMENTRY_NULL(jobject, boxPrimitive, (JNIEnv* env, jobject, jobject object)) if (object == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } JVMCIObject box = JVMCIENV->wrap(object); BasicType type = JVMCIENV->get_box_type(box); @@ -2165,7 +2165,7 @@ C2V_END C2V_VMENTRY_NULL(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } if (!klass->is_instance_klass()) { JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL); @@ -2192,7 +2192,7 @@ C2V_END C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } if (!klass->is_instance_klass()) { JVMCIObjectArray methods = JVMCIENV->new_ResolvedJavaMethod_array(0, JVMCI_CHECK_NULL); @@ -2219,7 +2219,7 @@ C2V_END C2V_VMENTRY_NULL(jobjectArray, getDeclaredFieldsInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } if (!klass->is_instance_klass()) { JVMCI_THROW_MSG_NULL(IllegalArgumentException, "not an InstanceKlass"); @@ -2346,7 +2346,7 @@ C2V_END C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, ARGUMENT_PAIR(expected_type), long displacement, jchar type_char)) if (object == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } // asConstant will throw an NPE if a constant contains null @@ -2396,7 +2396,7 @@ C2V_END C2V_VMENTRY_NULL(jobject, asJavaType, (JNIEnv* env, jobject, jobject object)) if (object == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL); if (java_lang_Class::is_instance(obj())) { @@ -2416,7 +2416,7 @@ C2V_END C2V_VMENTRY_NULL(jobject, asString, (JNIEnv* env, jobject, jobject object)) if (object == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL); const char* str = java_lang_String::as_utf8_string(obj()); @@ -2435,7 +2435,7 @@ C2V_END C2V_VMENTRY_NULL(jobject, getJavaMirror, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); if (klass == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } Handle mirror(THREAD, klass->java_mirror()); JVMCIObject result = JVMCIENV->get_object_constant(mirror()); @@ -2457,7 +2457,7 @@ C2V_VMENTRY_0(jint, getArrayLength, (JNIEnv* env, jobject, jobject x)) C2V_VMENTRY_NULL(jobject, readArrayElement, (JNIEnv* env, jobject, jobject x, int index)) if (x == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_NULL); if (xobj->klass()->is_array_klass()) { @@ -2543,16 +2543,16 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas } sl_handle = JVMCI::get_shared_library(sl_path, false); if (sl_handle == nullptr) { - JVMCI_THROW_MSG_0(InternalError, err_msg("Error initializing JVMCI runtime %d", runtime->id())); + JVMCI_THROW_MSG_NULL(InternalError, err_msg("Error initializing JVMCI runtime %d", runtime->id())); } } if (mirror == nullptr) { - JVMCI_THROW_0(NullPointerException); + JVMCI_THROW_NULL(NullPointerException); } Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror)); if (klass == nullptr || !klass->is_instance_klass()) { - JVMCI_THROW_MSG_0(IllegalArgumentException, "clazz is for primitive type"); + JVMCI_THROW_MSG_NULL(IllegalArgumentException, "clazz is for primitive type"); } InstanceKlass* iklass = InstanceKlass::cast(klass); @@ -2587,14 +2587,14 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas char* jni_long_name = st.as_string(); entry = (address) os::dll_lookup(sl_handle, jni_long_name); if (entry == nullptr) { - JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]", + JVMCI_THROW_MSG_NULL(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]", method->name_and_sig_as_C_string(), jni_name, jni_long_name, sl_path)); } } if (method->has_native_function() && entry != method->native_function()) { - JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [cannot re-link from " PTR_FORMAT " to " PTR_FORMAT "]", + JVMCI_THROW_MSG_NULL(UnsatisfiedLinkError, err_msg("%s [cannot re-link from " PTR_FORMAT " to " PTR_FORMAT "]", method->name_and_sig_as_C_string(), p2i(method->native_function()), p2i(entry))); } method->set_native_function(entry, Method::native_bind_event_is_interesting); @@ -2605,9 +2605,9 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas } } - typeArrayOop info_oop = oopFactory::new_longArray(4, CHECK_0); + typeArrayOop info_oop = oopFactory::new_longArray(4, CHECK_NULL); jlongArray info = (jlongArray) JNIHandles::make_local(THREAD, info_oop); - runtime->init_JavaVM_info(info, JVMCI_CHECK_0); + runtime->init_JavaVM_info(info, JVMCI_CHECK_NULL); return info; C2V_END @@ -3154,8 +3154,8 @@ C2V_VMENTRY_NULL(jobject, getThreadLocalObject, (JNIEnv* env, jobject, jint id)) if (id == 0) { return JNIHandles::make_local(thread->get_jvmci_reserved_oop0()); } - THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), - err_msg("%d is not a valid thread local id", id)); + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("%d is not a valid thread local id", id)); C2V_END C2V_VMENTRY(void, setThreadLocalLong, (JNIEnv* env, jobject, jint id, jlong value)) From 8e682aca24fba0803dceef513957fb2122895b87 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 13 Aug 2024 18:03:52 +0000 Subject: [PATCH 66/84] 8338158: Cleanup ShouldNotXXX uses in machnode.cpp Reviewed-by: chagedorn, kvn, dlong --- src/hotspot/share/opto/machnode.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/opto/machnode.cpp b/src/hotspot/share/opto/machnode.cpp index 39b804f7e5c..e271637893b 100644 --- a/src/hotspot/share/opto/machnode.cpp +++ b/src/hotspot/share/opto/machnode.cpp @@ -45,9 +45,9 @@ int MachOper::reg(PhaseRegAlloc *ra_, const Node *node, int idx) const { } intptr_t MachOper::constant() const { return 0x00; } relocInfo::relocType MachOper::constant_reloc() const { return relocInfo::none; } -jdouble MachOper::constantD() const { ShouldNotReachHere(); return 0.0; } -jfloat MachOper::constantF() const { ShouldNotReachHere(); return 0.0; } -jlong MachOper::constantL() const { ShouldNotReachHere(); return CONST64(0) ; } +jdouble MachOper::constantD() const { ShouldNotReachHere(); } +jfloat MachOper::constantF() const { ShouldNotReachHere(); } +jlong MachOper::constantL() const { ShouldNotReachHere(); } TypeOopPtr *MachOper::oop() const { return nullptr; } int MachOper::ccode() const { return 0x00; } // A zero, default, indicates this value is not needed. @@ -62,8 +62,8 @@ int MachOper::index_position() const { return -1; } // no index input // Check for PC-Relative displacement relocInfo::relocType MachOper::disp_reloc() const { return relocInfo::none; } // Return the label -Label* MachOper::label() const { ShouldNotReachHere(); return 0; } -intptr_t MachOper::method() const { ShouldNotReachHere(); return 0; } +Label* MachOper::label() const { ShouldNotReachHere(); } +intptr_t MachOper::method() const { ShouldNotReachHere(); } //------------------------------negate----------------------------------------- @@ -80,7 +80,6 @@ const Type *MachOper::type() const { //------------------------------in_RegMask------------------------------------- const RegMask *MachOper::in_RegMask(int index) const { ShouldNotReachHere(); - return nullptr; } //------------------------------dump_spec-------------------------------------- @@ -93,14 +92,12 @@ void MachOper::dump_spec(outputStream *st) const { } // Print any per-operand special info uint MachOper::hash() const { ShouldNotCallThis(); - return 5; } //------------------------------cmp-------------------------------------------- // Print any per-operand special info bool MachOper::cmp( const MachOper &oper ) const { ShouldNotCallThis(); - return opcode() == oper.opcode(); } //------------------------------hash------------------------------------------- @@ -207,7 +204,6 @@ void MachNode::fill_new_machnode(MachNode* node) const { // Return an equivalent instruction using memory for cisc_operand position MachNode *MachNode::cisc_version(int offset) { ShouldNotCallThis(); - return nullptr; } void MachNode::use_cisc_RegMask() { From 90527a57848f452be3be089a703cbc2af2d1657a Mon Sep 17 00:00:00 2001 From: Neethu Prasad Date: Tue, 13 Aug 2024 19:56:07 +0000 Subject: [PATCH 67/84] 8336742: Shenandoah: Add more verbose logging/stats for mark termination attempts Reviewed-by: shade, wkemper, rkennke --- .../gc/shenandoah/shenandoahConcurrentMark.cpp | 5 ++++- .../gc/shenandoah/shenandoahPhaseTimings.cpp | 16 ++++++++++------ .../gc/shenandoah/shenandoahPhaseTimings.hpp | 5 +++-- .../share/gc/shenandoah/shenandoahUtils.cpp | 6 +++--- .../share/gc/shenandoah/shenandoahUtils.hpp | 3 ++- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index dde446d824b..6ed75a9d961 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -206,7 +206,10 @@ void ShenandoahConcurrentMark::concurrent_mark() { } size_t before = qset.completed_buffers_num(); - Handshake::execute(&flush_satb); + { + ShenandoahTimingsTracker t(ShenandoahPhaseTimings::conc_mark_satb_flush, true); + Handshake::execute(&flush_satb); + } size_t after = qset.completed_buffers_num(); if (before == after) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp index 738657ac6bd..5e60cf92393 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp @@ -137,17 +137,21 @@ bool ShenandoahPhaseTimings::is_root_work_phase(Phase phase) { } } -void ShenandoahPhaseTimings::set_cycle_data(Phase phase, double time) { +void ShenandoahPhaseTimings::set_cycle_data(Phase phase, double time, bool should_aggregate) { + const double cycle_data = _cycle_data[phase]; + if (should_aggregate) { + _cycle_data[phase] = (cycle_data == uninitialized()) ? time : (cycle_data + time); + } else { #ifdef ASSERT - double d = _cycle_data[phase]; - assert(d == uninitialized(), "Should not be set yet: %s, current value: %lf", phase_name(phase), d); + assert(cycle_data == uninitialized(), "Should not be set yet: %s, current value: %lf", phase_name(phase), cycle_data); #endif - _cycle_data[phase] = time; + _cycle_data[phase] = time; + } } -void ShenandoahPhaseTimings::record_phase_time(Phase phase, double time) { +void ShenandoahPhaseTimings::record_phase_time(Phase phase, double time, bool should_aggregate) { if (!_policy->is_at_shutdown()) { - set_cycle_data(phase, time); + set_cycle_data(phase, time, should_aggregate); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp index a6ca335a0d7..01c83e08d37 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp @@ -57,6 +57,7 @@ class outputStream; f(conc_mark_roots, "Concurrent Mark Roots ") \ SHENANDOAH_PAR_PHASE_DO(conc_mark_roots, " CMR: ", f) \ f(conc_mark, "Concurrent Marking") \ + f(conc_mark_satb_flush, " Flush SATB") \ \ f(final_mark_gross, "Pause Final Mark (G)") \ f(final_mark, "Pause Final Mark (N)") \ @@ -216,13 +217,13 @@ class ShenandoahPhaseTimings : public CHeapObj { ShenandoahWorkerData* worker_data(Phase phase, ParPhase par_phase); Phase worker_par_phase(Phase phase, ParPhase par_phase); - void set_cycle_data(Phase phase, double time); + void set_cycle_data(Phase phase, double time, bool should_aggregate = false); static double uninitialized() { return -1; } public: ShenandoahPhaseTimings(uint max_workers); - void record_phase_time(Phase phase, double time); + void record_phase_time(Phase phase, double time, bool should_aggregate = false); void record_workers_start(Phase phase); void record_workers_end(Phase phase); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp index 64074a9672c..ca56b06e79d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.cpp @@ -111,8 +111,8 @@ ShenandoahConcurrentPhase::~ShenandoahConcurrentPhase() { _timer->register_gc_concurrent_end(); } -ShenandoahTimingsTracker::ShenandoahTimingsTracker(ShenandoahPhaseTimings::Phase phase) : - _timings(ShenandoahHeap::heap()->phase_timings()), _phase(phase) { +ShenandoahTimingsTracker::ShenandoahTimingsTracker(ShenandoahPhaseTimings::Phase phase, bool should_aggregate) : + _timings(ShenandoahHeap::heap()->phase_timings()), _phase(phase), _should_aggregate(should_aggregate) { assert(Thread::current()->is_VM_thread() || Thread::current()->is_ConcurrentGC_thread(), "Must be set by these threads"); _parent_phase = _current_phase; @@ -121,7 +121,7 @@ ShenandoahTimingsTracker::ShenandoahTimingsTracker(ShenandoahPhaseTimings::Phase } ShenandoahTimingsTracker::~ShenandoahTimingsTracker() { - _timings->record_phase_time(_phase, os::elapsedTime() - _start); + _timings->record_phase_time(_phase, os::elapsedTime() - _start, _should_aggregate); _current_phase = _parent_phase; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp index 15f0ee61407..ffa9d764d3c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUtils.hpp @@ -64,11 +64,12 @@ class ShenandoahTimingsTracker : public StackObj { ShenandoahPhaseTimings* const _timings; const ShenandoahPhaseTimings::Phase _phase; + const bool _should_aggregate; ShenandoahPhaseTimings::Phase _parent_phase; double _start; public: - ShenandoahTimingsTracker(ShenandoahPhaseTimings::Phase phase); + ShenandoahTimingsTracker(ShenandoahPhaseTimings::Phase phase, bool should_aggregate = false); ~ShenandoahTimingsTracker(); static ShenandoahPhaseTimings::Phase current_phase() { return _current_phase; } From f132b347e13a57d9654f0ab11db0636999576036 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Tue, 13 Aug 2024 22:59:13 +0000 Subject: [PATCH 68/84] 8336854: CAInterop.java#actalisauthenticationrootca conflicted with /manual and /timeout Reviewed-by: rhalade --- .../cert/CertPathValidator/certification/CAInterop.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java index 889926077a9..ab04391b1f3 100644 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java @@ -25,14 +25,16 @@ * @test id=actalisauthenticationrootca * @bug 8189131 * @summary Interoperability tests with Actalis CA + * Before this test set to manual, the original timeout + * value if 180 * @library /test/lib * @build jtreg.SkippedException ValidatePathWithURL CAInterop * @run main/othervm/manual -Djava.security.debug=certpath,ocsp * CAInterop actalisauthenticationrootca OCSP - * @run main/othervm/manual/timeout=180 -Djava.security.debug=certpath,ocsp + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp * -Dcom.sun.security.ocsp.useget=false * CAInterop actalisauthenticationrootca OCSP - * @run main/othervm/manual/timeout=180 -Djava.security.debug=certpath,ocsp + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp * CAInterop actalisauthenticationrootca CRL */ From 720b44648bcff997278af92746f942b2425298a5 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 14 Aug 2024 05:42:14 +0000 Subject: [PATCH 69/84] 8335181: Incorrect handling of HTTP/2 GOAWAY frames in HttpClient Reviewed-by: dfuchs --- .../jdk/internal/net/http/ExchangeImpl.java | 15 +- .../internal/net/http/Http2Connection.java | 58 ++- .../jdk/internal/net/http/MultiExchange.java | 27 +- .../classes/jdk/internal/net/http/Stream.java | 67 +++- .../internal/net/http/WindowController.java | 13 +- .../internal/net/http/frame/GoAwayFrame.java | 6 +- .../net/httpclient/http2/H2GoAwayTest.java | 336 ++++++++++++++++++ .../test/lib/common/HttpServerAdapters.java | 30 +- .../test/lib/http2/Http2TestExchange.java | 8 +- .../test/lib/http2/Http2TestExchangeImpl.java | 5 + .../test/lib/http2/Http2TestServer.java | 14 +- .../lib/http2/Http2TestServerConnection.java | 102 +++++- 12 files changed, 625 insertions(+), 56 deletions(-) create mode 100644 test/jdk/java/net/httpclient/http2/H2GoAwayTest.java diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java index 854ea73cc36..404f970cc59 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,10 @@ abstract class ExchangeImpl { final Exchange exchange; + // this will be set to true only when the peer explicitly states (through a GOAWAY frame or + // a relevant error code in reset frame) that the corresponding stream (id) wasn't processed + private volatile boolean unprocessedByPeer; + ExchangeImpl(Exchange e) { // e == null means a http/2 pushed stream this.exchange = e; @@ -265,4 +269,13 @@ void upgraded() { } // Called when server returns non 100 response to // an Expect-Continue void expectContinueFailed(int rcode) { } + + final boolean isUnprocessedByPeer() { + return this.unprocessedByPeer; + } + + // Marks the exchange as unprocessed by the peer + final void markUnprocessedByPeer() { + this.unprocessedByPeer = true; + } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java index 3321ffdfce0..9457ff69988 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Flow; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; @@ -358,6 +360,7 @@ private record PushContinuationState(HeaderDecoder pushContDecoder, PushPromiseF private final String key; // for HttpClientImpl.connections map private final FramesDecoder framesDecoder; private final FramesEncoder framesEncoder = new FramesEncoder(); + private final AtomicLong lastProcessedStreamInGoAway = new AtomicLong(-1); /** * Send Window controller for both connection and stream windows. @@ -725,7 +728,9 @@ final int maxConcurrentServerInitiatedStreams() { void close() { if (markHalfClosedLocal()) { - if (connection.channel().isOpen()) { + // we send a GOAWAY frame only if the remote side hasn't already indicated + // the intention to close the connection by previously sending a GOAWAY of its own + if (connection.channel().isOpen() && !isMarked(closedState, HALF_CLOSED_REMOTE)) { Log.logTrace("Closing HTTP/2 connection: to {0}", connection.address()); GoAwayFrame f = new GoAwayFrame(0, ErrorFrame.NO_ERROR, @@ -1205,13 +1210,46 @@ private void handlePing(PingFrame frame) sendUnorderedFrame(frame); } - private void handleGoAway(GoAwayFrame frame) - throws IOException - { - if (markHalfClosedLRemote()) { - shutdown(new IOException( - connection.channel().getLocalAddress() - + ": GOAWAY received")); + private void handleGoAway(final GoAwayFrame frame) { + final long lastProcessedStream = frame.getLastStream(); + assert lastProcessedStream >= 0 : "unexpected last stream id: " + + lastProcessedStream + " in GOAWAY frame"; + + markHalfClosedRemote(); + setFinalStream(); // don't allow any new streams on this connection + if (debug.on()) { + debug.log("processing incoming GOAWAY with last processed stream id:%s in frame %s", + lastProcessedStream, frame); + } + // see if this connection has previously received a GOAWAY from the peer and if yes + // then check if this new last processed stream id is lesser than the previous + // known last processed stream id. Only update the last processed stream id if the new + // one is lesser than the previous one. + long prevLastProcessed = lastProcessedStreamInGoAway.get(); + while (prevLastProcessed == -1 || lastProcessedStream < prevLastProcessed) { + if (lastProcessedStreamInGoAway.compareAndSet(prevLastProcessed, + lastProcessedStream)) { + break; + } + prevLastProcessed = lastProcessedStreamInGoAway.get(); + } + handlePeerUnprocessedStreams(lastProcessedStreamInGoAway.get()); + } + + private void handlePeerUnprocessedStreams(final long lastProcessedStream) { + final AtomicInteger numClosed = new AtomicInteger(); // atomic merely to allow usage within lambda + streams.forEach((id, exchange) -> { + if (id > lastProcessedStream) { + // any streams with an stream id higher than the last processed stream + // can be retried (on a new connection). we close the exchange as unprocessed + // to facilitate the retrying. + client2.client().theExecutor().ensureExecutedAsync(exchange::closeAsUnprocessed); + numClosed.incrementAndGet(); + } + }); + if (debug.on()) { + debug.log(numClosed.get() + " stream(s), with id greater than " + lastProcessedStream + + ", will be closed as unprocessed"); } } @@ -1745,7 +1783,7 @@ private boolean markHalfClosedLocal() { return markClosedState(HALF_CLOSED_LOCAL); } - private boolean markHalfClosedLRemote() { + private boolean markHalfClosedRemote() { return markClosedState(HALF_CLOSED_REMOTE); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java index d6d03a9aa8a..2c15a704ef9 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,7 @@ class MultiExchange implements Cancelable { Exchange exchange; // the current exchange Exchange previous; volatile Throwable retryCause; - volatile boolean expiredOnce; + volatile boolean retriedOnce; volatile HttpResponse response; // Maximum number of times a request will be retried/redirected @@ -469,7 +469,7 @@ private CompletableFuture responseAsyncImpl() { return exch.ignoreBody().handle((r,t) -> { previousreq = currentreq; currentreq = newrequest; - expiredOnce = false; + retriedOnce = false; setExchange(new Exchange<>(currentreq, this, acc)); return responseAsyncImpl(); }).thenCompose(Function.identity()); @@ -482,7 +482,7 @@ private CompletableFuture responseAsyncImpl() { return completedFuture(response); } // all exceptions thrown are handled here - CompletableFuture errorCF = getExceptionalCF(ex); + CompletableFuture errorCF = getExceptionalCF(ex, exch.exchImpl); if (errorCF == null) { return responseAsyncImpl(); } else { @@ -554,36 +554,39 @@ private Throwable retryCause(Throwable t) { * Takes a Throwable and returns a suitable CompletableFuture that is * completed exceptionally, or null. */ - private CompletableFuture getExceptionalCF(Throwable t) { + private CompletableFuture getExceptionalCF(Throwable t, ExchangeImpl exchImpl) { if ((t instanceof CompletionException) || (t instanceof ExecutionException)) { if (t.getCause() != null) { t = t.getCause(); } } + final boolean retryAsUnprocessed = exchImpl != null && exchImpl.isUnprocessedByPeer(); if (cancelled && !requestCancelled() && t instanceof IOException) { if (!(t instanceof HttpTimeoutException)) { t = toTimeoutException((IOException)t); } - } else if (retryOnFailure(t)) { + } else if (retryAsUnprocessed || retryOnFailure(t)) { Throwable cause = retryCause(t); if (!(t instanceof ConnectException)) { // we may need to start a new connection, and if so // we want to start with a fresh connect timeout again. if (connectTimeout != null) connectTimeout.reset(); - if (!canRetryRequest(currentreq)) { - return failedFuture(cause); // fails with original cause + if (!retryAsUnprocessed && !canRetryRequest(currentreq)) { + // a (peer) processed request which cannot be retried, fail with + // the original cause + return failedFuture(cause); } } // ConnectException: retry, but don't reset the connectTimeout. // allow the retry mechanism to do its work retryCause = cause; - if (!expiredOnce) { + if (!retriedOnce) { if (debug.on()) { debug.log(t.getClass().getSimpleName() - + " (async): retrying due to: ", t); + + " (async): retrying " + currentreq + " due to: ", t); } - expiredOnce = true; + retriedOnce = true; // The connection was abruptly closed. // We return null to retry the same request a second time. // The request filters have already been applied to the @@ -594,7 +597,7 @@ private CompletableFuture getExceptionalCF(Throwable t) { } else { if (debug.on()) { debug.log(t.getClass().getSimpleName() - + " (async): already retried once.", t); + + " (async): already retried once " + currentreq, t); } t = cause; } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java index 1bb520a6fb1..1a007e82adc 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java @@ -641,20 +641,39 @@ void handleReset(ResetFrame frame, Flow.Subscriber subscriber) { stateLock.unlock(); } try { - int error = frame.getErrorCode(); - IOException e = new IOException("Received RST_STREAM: " - + ErrorFrame.stringForCode(error)); - if (errorRef.compareAndSet(null, e)) { - if (subscriber != null) { - subscriber.onError(e); + final int error = frame.getErrorCode(); + // A REFUSED_STREAM error code implies that the stream wasn't processed by the + // peer and the client is free to retry the request afresh. + if (error == ErrorFrame.REFUSED_STREAM) { + // Here we arrange for the request to be retried. Note that we don't call + // closeAsUnprocessed() method here because the "closed" state is already set + // to true a few lines above and calling close() from within + // closeAsUnprocessed() will end up being a no-op. We instead do the additional + // bookkeeping here. + markUnprocessedByPeer(); + errorRef.compareAndSet(null, new IOException("request not processed by peer")); + if (debug.on()) { + debug.log("request unprocessed by peer (REFUSED_STREAM) " + this.request); + } + } else { + final String reason = ErrorFrame.stringForCode(error); + final IOException failureCause = new IOException("Received RST_STREAM: " + reason); + if (debug.on()) { + debug.log(streamid + " received RST_STREAM with code: " + reason); + } + if (errorRef.compareAndSet(null, failureCause)) { + if (subscriber != null) { + subscriber.onError(failureCause); + } } } - completeResponseExceptionally(e); + final Throwable failureCause = errorRef.get(); + completeResponseExceptionally(failureCause); if (!requestBodyCF.isDone()) { - requestBodyCF.completeExceptionally(errorRef.get()); // we may be sending the body.. + requestBodyCF.completeExceptionally(failureCause); // we may be sending the body.. } if (responseBodyCF != null) { - responseBodyCF.completeExceptionally(errorRef.get()); + responseBodyCF.completeExceptionally(failureCause); } } finally { connection.decrementStreamsCount(streamid); @@ -1663,7 +1682,35 @@ Throwable getCancelCause() { } final String dbgString() { - return connection.dbgString() + "/Stream("+streamid+")"; + final int id = streamid; + final String sid = id == 0 ? "?" : String.valueOf(id); + return connection.dbgString() + "/Stream(" + sid + ")"; + } + + /** + * An unprocessed exchange is one that hasn't been processed by a peer. The local end of the + * connection would be notified about such exchanges when it receives a GOAWAY frame with + * a stream id that tells which exchanges have been unprocessed. + * This method is called on such unprocessed exchanges and the implementation of this method + * will arrange for the request, corresponding to this exchange, to be retried afresh on a + * new connection. + */ + void closeAsUnprocessed() { + try { + // We arrange for the request to be retried on a new connection as allowed by the RFC-9113 + markUnprocessedByPeer(); + this.errorRef.compareAndSet(null, new IOException("request not processed by peer")); + if (debug.on()) { + debug.log("closing " + this.request + " as unprocessed by peer"); + } + // close the exchange and complete the response CF exceptionally + close(); + completeResponseExceptionally(this.errorRef.get()); + } finally { + // decrementStreamsCount isn't really needed but we do it to make sure + // the log messages, where these counts/states get reported, show the accurate state. + connection.decrementStreamsCount(streamid); + } } private class HeadersConsumer extends ValidatingHeadersConsumer { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java b/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java index 1df81640345..a30c21a7a7d 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/WindowController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,13 +100,16 @@ void removeStream(int streamid) { controllerLock.lock(); try { Integer old = streams.remove(streamid); - // Odd stream numbers (client streams) should have been registered. + // A client initiated stream might be closed (as unprocessed, due to a + // GOAWAY received on the connection) even before the stream is + // registered with this WindowController instance (when sending out request headers). + // Thus, for client initiated streams, we don't enforce the presence of the + // stream in the registered "streams" map. + // Even stream numbers (server streams - aka Push Streams) should // not be registered final boolean isClientStream = (streamid & 0x1) == 1; - if (old == null && isClientStream) { - throw new InternalError("Expected entry for streamid: " + streamid); - } else if (old != null && !isClientStream) { + if (old != null && !isClientStream) { throw new InternalError("Unexpected entry for streamid: " + streamid); } } finally { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java b/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java index 45ec7553f5a..662e5dd98b3 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/frame/GoAwayFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,9 @@ int length() { @Override public String toString() { - return super.toString() + " Debugdata: " + new String(debugData, UTF_8); + return super.toString() + + " lastStreamId=" + lastStream + + ", Debugdata: " + new String(debugData, UTF_8); } public int getLastStream() { diff --git a/test/jdk/java/net/httpclient/http2/H2GoAwayTest.java b/test/jdk/java/net/httpclient/http2/H2GoAwayTest.java new file mode 100644 index 00000000000..755bb2e16cc --- /dev/null +++ b/test/jdk/java/net/httpclient/http2/H2GoAwayTest.java @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.net.ssl.SSLContext; + +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestExchange; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestHandler; +import jdk.httpclient.test.lib.common.HttpServerAdapters.HttpTestServer; +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static java.net.http.HttpClient.Version.HTTP_2; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; + +/* + * @test + * @bug 8335181 + * @summary verify that the HttpClient correctly handles incoming GOAWAY frames and + * retries any unprocessed requests on a new connection + * @library /test/lib /test/jdk/java/net/httpclient/lib + * @build jdk.httpclient.test.lib.common.HttpServerAdapters + * jdk.test.lib.net.SimpleSSLContext + * @run junit H2GoAwayTest + */ +public class H2GoAwayTest { + private static final String REQ_PATH = "/test"; + private static HttpTestServer server; + private static String REQ_URI_BASE; + private static SSLContext sslCtx; + + @BeforeAll + static void beforeAll() throws Exception { + sslCtx = new SimpleSSLContext().get(); + assertNotNull(sslCtx, "SSLContext couldn't be created"); + server = HttpTestServer.create(HTTP_2, sslCtx); + server.addHandler(new Handler(), REQ_PATH); + server.start(); + System.out.println("Server started at " + server.getAddress()); + REQ_URI_BASE = URIBuilder.newBuilder().scheme("https") + .loopback() + .port(server.getAddress().getPort()) + .path(REQ_PATH) + .build().toString(); + } + + @AfterAll + static void afterAll() { + if (server != null) { + System.out.println("Stopping server at " + server.getAddress()); + server.stop(); + } + } + + /** + * Verifies that when several requests are sent using send() and the server + * connection is configured to send a GOAWAY after processing only a few requests, then + * the remaining requests are retried on a different connection + */ + @Test + public void testSequential() throws Exception { + final LimitedPerConnRequestApprover reqApprover = new LimitedPerConnRequestApprover(); + server.setRequestApprover(reqApprover::allowNewRequest); + try (final HttpClient client = HttpClient.newBuilder().version(HTTP_2) + .sslContext(sslCtx).build()) { + final String[] reqMethods = {"HEAD", "GET", "POST"}; + for (final String reqMethod : reqMethods) { + final int numReqs = LimitedPerConnRequestApprover.MAX_REQS_PER_CONN + 3; + final Set connectionKeys = new LinkedHashSet<>(); + for (int i = 1; i <= numReqs; i++) { + final URI reqURI = new URI(REQ_URI_BASE + "?seq&" + reqMethod + "=" + i); + final HttpRequest req = HttpRequest.newBuilder() + .uri(reqURI) + .method(reqMethod, HttpRequest.BodyPublishers.noBody()) + .build(); + System.out.println("initiating request " + req); + final HttpResponse resp = client.send(req, BodyHandlers.ofString()); + final String respBody = resp.body(); + System.out.println("received response: " + respBody); + assertEquals(200, resp.statusCode(), + "unexpected status code for request " + resp.request()); + // response body is the logical key of the connection on which the + // request was handled + connectionKeys.add(respBody); + } + System.out.println("connections involved in handling the requests: " + + connectionKeys); + // all requests have finished, we now just do a basic check that + // more than one connection was involved in processing these requests + assertEquals(2, connectionKeys.size(), + "unexpected number of connections " + connectionKeys); + } + } finally { + server.setRequestApprover(null); // reset + } + } + + /** + * Verifies that when a server responds with a GOAWAY and then never processes the new retried + * requests on a new connection too, then the application code receives the request failure. + * This tests the send() API of the HttpClient. + */ + @Test + public void testUnprocessedRaisesException() throws Exception { + try (final HttpClient client = HttpClient.newBuilder().version(HTTP_2) + .sslContext(sslCtx).build()) { + final Random random = new Random(); + final String[] reqMethods = {"HEAD", "GET", "POST"}; + for (final String reqMethod : reqMethods) { + final int maxAllowedReqs = 2; + final int numReqs = maxAllowedReqs + 3; // 3 more requests than max allowed + // configure the approver + final LimitedRequestApprover reqApprover = new LimitedRequestApprover(maxAllowedReqs); + server.setRequestApprover(reqApprover::allowNewRequest); + try { + int numSuccess = 0; + int numFailed = 0; + for (int i = 1; i <= numReqs; i++) { + final String reqQueryPart = "?sync&" + reqMethod + "=" + i; + final URI reqURI = new URI(REQ_URI_BASE + reqQueryPart); + final HttpRequest req = HttpRequest.newBuilder() + .uri(reqURI) + .method(reqMethod, HttpRequest.BodyPublishers.noBody()) + .build(); + System.out.println("initiating request " + req); + if (i <= maxAllowedReqs) { + // expected to successfully complete + numSuccess++; + final HttpResponse resp = client.send(req, BodyHandlers.ofString()); + final String respBody = resp.body(); + System.out.println("received response: " + respBody); + assertEquals(200, resp.statusCode(), + "unexpected status code for request " + resp.request()); + } else { + // expected to fail as unprocessed + try { + final HttpResponse resp = client.send(req, BodyHandlers.ofString()); + fail("Request was expected to fail as unprocessed," + + " but got response: " + resp.body() + ", status code: " + + resp.statusCode()); + } catch (IOException ioe) { + // verify it failed for the right reason + if (ioe.getMessage() == null + || !ioe.getMessage().contains("request not processed by peer")) { + // propagate the original failure + throw ioe; + } + numFailed++; // failed due to right reason + System.out.println("received expected failure: " + ioe + + ", for request " + reqURI); + } + } + } + // verify the correct number of requests succeeded/failed + assertEquals(maxAllowedReqs, numSuccess, "unexpected number of requests succeeded"); + assertEquals((numReqs - maxAllowedReqs), numFailed, "unexpected number of requests failed"); + } finally { + server.setRequestApprover(null); // reset + } + } + } + } + + /** + * Verifies that when a server responds with a GOAWAY and then never processes the new retried + * requests on a new connection too, then the application code receives the request failure. + * This tests the sendAsync() API of the HttpClient. + */ + @Test + public void testUnprocessedRaisesExceptionAsync() throws Throwable { + try (final HttpClient client = HttpClient.newBuilder().version(HTTP_2) + .sslContext(sslCtx).build()) { + final Random random = new Random(); + final String[] reqMethods = {"HEAD", "GET", "POST"}; + for (final String reqMethod : reqMethods) { + final int maxAllowedReqs = 2; + final int numReqs = maxAllowedReqs + 3; // 3 more requests than max allowed + // configure the approver + final LimitedRequestApprover reqApprover = new LimitedRequestApprover(maxAllowedReqs); + server.setRequestApprover(reqApprover::allowNewRequest); + try { + final List>> futures = new ArrayList<>(); + for (int i = 1; i <= numReqs; i++) { + final URI reqURI = new URI(REQ_URI_BASE + "?async&" + reqMethod + "=" + i); + final HttpRequest req = HttpRequest.newBuilder() + .uri(reqURI) + .method(reqMethod, HttpRequest.BodyPublishers.noBody()) + .build(); + System.out.println("initiating request " + req); + final Future> f = client.sendAsync(req, BodyHandlers.ofString()); + futures.add(f); + } + // wait for responses + int numFailed = 0; + int numSuccess = 0; + for (int i = 1; i <= numReqs; i++) { + final String reqQueryPart = "?async&" + reqMethod + "=" + i; + try { + System.out.println("waiting response of request " + + REQ_URI_BASE + reqQueryPart); + final HttpResponse resp = futures.get(i - 1).get(); + numSuccess++; + final String respBody = resp.body(); + System.out.println("request: " + resp.request() + + ", received response: " + respBody); + assertEquals(200, resp.statusCode(), + "unexpected status code for request " + resp.request()); + } catch (ExecutionException ee) { + final Throwable cause = ee.getCause(); + if (!(cause instanceof IOException ioe)) { + throw cause; + } + // verify it failed for the right reason + if (ioe.getMessage() == null + || !ioe.getMessage().contains("request not processed by peer")) { + // propagate the original failure + throw ioe; + } + numFailed++; // failed due to the right reason + System.out.println("received expected failure: " + ioe + + ", for request " + REQ_URI_BASE + reqQueryPart); + } + } + // verify the correct number of requests succeeded/failed + assertEquals(maxAllowedReqs, numSuccess, "unexpected number of requests succeeded"); + assertEquals((numReqs - maxAllowedReqs), numFailed, "unexpected number of requests failed"); + } finally { + server.setRequestApprover(null); // reset + } + } + } + } + + // only allows fixed number of requests, irrespective of which server connection handles + // it. requests that are rejected will either be sent a GOAWAY on the connection + // or a RST_FRAME with a REFUSED_STREAM on the stream + private static final class LimitedRequestApprover { + private final int maxAllowedReqs; + private final AtomicInteger numApproved = new AtomicInteger(); + + private LimitedRequestApprover(final int maxAllowedReqs) { + this.maxAllowedReqs = maxAllowedReqs; + } + + public boolean allowNewRequest(final String serverConnKey) { + final int approved = numApproved.incrementAndGet(); + return approved <= maxAllowedReqs; + } + } + + // allows a certain number of requests per server connection. + // requests that are rejected will either be sent a GOAWAY on the connection + // or a RST_FRAME with a REFUSED_STREAM on the stream + private static final class LimitedPerConnRequestApprover { + private static final int MAX_REQS_PER_CONN = 6; + private final Map numApproved = + new ConcurrentHashMap<>(); + private final Map numDisapproved = + new ConcurrentHashMap<>(); + + public boolean allowNewRequest(final String serverConnKey) { + final AtomicInteger approved = numApproved.computeIfAbsent(serverConnKey, + (k) -> new AtomicInteger()); + int curr = approved.get(); + while (curr < MAX_REQS_PER_CONN) { + if (approved.compareAndSet(curr, curr + 1)) { + return true; // new request allowed + } + curr = approved.get(); + } + final AtomicInteger disapproved = numDisapproved.computeIfAbsent(serverConnKey, + (k) -> new AtomicInteger()); + final int numUnprocessed = disapproved.incrementAndGet(); + System.out.println(approved.get() + " processed, " + + numUnprocessed + " unprocessed requests on connection " + serverConnKey); + return false; + } + } + + private static final class Handler implements HttpTestHandler { + + @Override + public void handle(final HttpTestExchange exchange) throws IOException { + final String connectionKey = exchange.getConnectionKey(); + System.out.println("responding to request: " + exchange.getRequestURI() + + " on connection " + connectionKey); + final byte[] response = connectionKey.getBytes(UTF_8); + exchange.sendResponseHeaders(200, response.length); + try (final OutputStream os = exchange.getResponseBody()) { + os.write(response); + } + } + } +} diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java index e18dd87a507..36498684a9a 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/HttpServerAdapters.java @@ -58,6 +58,7 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; +import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -239,6 +240,7 @@ public static abstract class HttpTestExchange implements AutoCloseable { public abstract String getRequestMethod(); public abstract void close(); public abstract InetSocketAddress getRemoteAddress(); + public abstract String getConnectionKey(); public void serverPush(URI uri, HttpHeaders headers, byte[] body) { ByteArrayInputStream bais = new ByteArrayInputStream(body); serverPush(uri, headers, bais); @@ -253,7 +255,7 @@ public static HttpTestExchange of(HttpExchange exchange) { return new Http1TestExchange(exchange); } public static HttpTestExchange of(Http2TestExchange exchange) { - return new Http2TestExchangeImpl(exchange); + return new H2ExchangeImpl(exchange); } abstract void doFilter(Filter.Chain chain) throws IOException; @@ -306,15 +308,21 @@ public InetSocketAddress getRemoteAddress() { public URI getRequestURI() { return exchange.getRequestURI(); } @Override public String getRequestMethod() { return exchange.getRequestMethod(); } + + @Override + public String getConnectionKey() { + return exchange.getLocalAddress() + "->" + exchange.getRemoteAddress(); + } + @Override public String toString() { return this.getClass().getSimpleName() + ": " + exchange.toString(); } } - private static final class Http2TestExchangeImpl extends HttpTestExchange { + private static final class H2ExchangeImpl extends HttpTestExchange { private final Http2TestExchange exchange; - Http2TestExchangeImpl(Http2TestExchange exch) { + H2ExchangeImpl(Http2TestExchange exch) { this.exchange = exch; } @Override @@ -363,6 +371,11 @@ public InetSocketAddress getRemoteAddress() { return exchange.getRemoteAddress(); } + @Override + public String getConnectionKey() { + return exchange.getConnectionKey(); + } + @Override public URI getRequestURI() { return exchange.getRequestURI(); } @Override @@ -708,6 +721,7 @@ static void enableLogging() { public abstract HttpTestContext addHandler(HttpTestHandler handler, String root); public abstract InetSocketAddress getAddress(); public abstract Version getVersion(); + public abstract void setRequestApprover(final Predicate approver); public String serverAuthority() { InetSocketAddress address = getAddress(); @@ -856,6 +870,11 @@ public InetSocketAddress getAddress() { impl.getAddress().getPort()); } public Version getVersion() { return Version.HTTP_1_1; } + + @Override + public void setRequestApprover(final Predicate approver) { + throw new UnsupportedOperationException("not supported"); + } } private static class Http1TestContext extends HttpTestContext { @@ -907,6 +926,11 @@ public InetSocketAddress getAddress() { impl.getAddress().getPort()); } public Version getVersion() { return Version.HTTP_2; } + + @Override + public void setRequestApprover(final Predicate approver) { + this.impl.setRequestApprover(approver); + } } private static class Http2TestContext diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchange.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchange.java index 208a8d54e08..d982349dac5 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchange.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchange.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,4 +71,10 @@ public interface Http2TestExchange { * It may also complete exceptionally */ CompletableFuture sendPing(); + + /** + * {@return the identification of the connection on which this exchange is being + * processed} + */ + String getConnectionKey(); } diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchangeImpl.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchangeImpl.java index 63a4de6ef90..d25019f9094 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchangeImpl.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestExchangeImpl.java @@ -220,6 +220,11 @@ public void serverPush(URI uri, HttpHeaders headers, InputStream content) { } } + @Override + public String getConnectionKey() { + return conn.connectionKey(); + } + private boolean isHeadRequest() { return HEAD.equalsIgnoreCase(getRequestMethod()); } diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServer.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServer.java index ffa05d5c11c..ca7e7d3dc30 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServer.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; + import javax.net.ServerSocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLParameters; @@ -59,6 +61,8 @@ public class Http2TestServer implements AutoCloseable { final Set connections; final Properties properties; final String name; + // request approver which takes the server connection key as the input + private volatile Predicate newRequestApprover; private static ThreadFactory defaultThreadFac = (Runnable r) -> { @@ -285,6 +289,14 @@ public String serverName() { return serverName; } + public void setRequestApprover(final Predicate approver) { + this.newRequestApprover = approver; + } + + Predicate getRequestApprover() { + return this.newRequestApprover; + } + private synchronized void putConnection(InetSocketAddress addr, Http2TestServerConnection c) { if (!stopping) connections.add(c); diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java index ff10d4087e9..1aeeee60b19 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http2/Http2TestServerConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,13 +75,18 @@ import java.util.Optional; import java.util.Properties; import java.util.Random; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiPredicate; import java.util.function.Consumer; +import java.util.function.Predicate; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; +import static jdk.internal.net.http.frame.ErrorFrame.REFUSED_STREAM; import static jdk.internal.net.http.frame.SettingsFrame.HEADER_TABLE_SIZE; /** @@ -110,6 +115,10 @@ public class Http2TestServerConnection { volatile boolean stopping; volatile int nextPushStreamId = 2; ConcurrentLinkedQueue pings = new ConcurrentLinkedQueue<>(); + // the max stream id of a processed H2 request. -1 implies none were processed. + private final AtomicInteger maxProcessedRequestStreamId = new AtomicInteger(-1); + // the stream id that was sent in a GOAWAY frame. -1 implies no GOAWAY frame was sent. + private final AtomicInteger goAwayRequestStreamId = new AtomicInteger(-1); final static ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); final static byte[] EMPTY_BARRAY = new byte[0]; @@ -234,11 +243,29 @@ CompletableFuture sendPing() { return ping.response(); } - void goAway(int error) throws IOException { - int laststream = nextstream >= 3 ? nextstream - 2 : 1; - - GoAwayFrame go = new GoAwayFrame(laststream, error); - outputQ.put(go); + private void sendGoAway(final int error) throws IOException { + int maxProcessedStreamId = maxProcessedRequestStreamId.get(); + if (maxProcessedStreamId == -1) { + maxProcessedStreamId = 0; + } + boolean send = false; + int currentGoAwayReqStrmId = goAwayRequestStreamId.get(); + // update the last processed stream id and send a goaway frame if the new last processed + // stream id is lesser than the last processed stream id sent in + // a previous goaway frame (if any) + while (currentGoAwayReqStrmId == -1 || maxProcessedStreamId < currentGoAwayReqStrmId) { + if (goAwayRequestStreamId.compareAndSet(currentGoAwayReqStrmId, maxProcessedStreamId)) { + send = true; + break; + } + currentGoAwayReqStrmId = goAwayRequestStreamId.get(); + } + if (!send) { + return; + } + final GoAwayFrame frame = new GoAwayFrame(maxProcessedStreamId, error); + outputQ.put(frame); + System.err.println("Sending GOAWAY frame " + frame + " from server connection " + this); } /** @@ -331,8 +358,9 @@ void close(int error) { q.orderlyClose(); }); try { - if (error != -1) - goAway(error); + if (error != -1) { + sendGoAway(error); + } outputQ.orderlyClose(); socket.close(); } catch (Exception e) { @@ -612,6 +640,14 @@ void createPrimordialStream(Http1InitialRequest request) throws IOException { path = path + "?" + uri.getRawQuery(); headersBuilder.setHeader(":path", path); + // skip processing the request if configured to do so + final String connKey = connectionKey(); + if (!shouldProcessNewHTTPRequest(connKey)) { + System.err.println("Rejecting primordial stream 1 and sending GOAWAY" + + " on server connection " + connKey + ", for request: " + path); + sendGoAway(ErrorFrame.NO_ERROR); + return; + } Queue q = new Queue(sentinel); byte[] body = getRequestBody(request); addHeaders(getHeaders(request.headers), headersBuilder); @@ -620,11 +656,24 @@ void createPrimordialStream(Http1InitialRequest request) throws IOException { addRequestBodyToQueue(body, q); streams.put(1, q); + maxProcessedRequestStreamId.set(1); exec.submit(() -> { handleRequest(headers, q, 1, true /*complete request has been read*/); }); } + private boolean shouldProcessNewHTTPRequest(final String serverConnKey) { + final Predicate approver = this.server.getRequestApprover(); + if (approver == null) { + return true; // process the request + } + return approver.test(serverConnKey); + } + + final String connectionKey() { + return this.server.getAddress() + "->" + this.socket.getRemoteSocketAddress(); + } + // all other streams created here @SuppressWarnings({"rawtypes","unchecked"}) void createStream(HeaderFrame frame) throws IOException { @@ -632,7 +681,7 @@ void createStream(HeaderFrame frame) throws IOException { frames.add(frame); int streamid = frame.streamid(); if (streamid != nextstream) { - throw new IOException("unexpected stream id"); + throw new IOException("unexpected stream id: " + streamid); } nextstream += 2; @@ -663,12 +712,30 @@ void createStream(HeaderFrame frame) throws IOException { throw new IOException("Unexpected Upgrade in headers:" + headers); } disallowedHeader = headers.firstValue("HTTP2-Settings"); - if (disallowedHeader.isPresent()) + if (disallowedHeader.isPresent()) { throw new IOException("Unexpected HTTP2-Settings in headers:" + headers); + } - + // skip processing the request if the server is configured to do so + final String connKey = connectionKey(); + final String path = headers.firstValue(":path").orElse(""); + if (!shouldProcessNewHTTPRequest(connKey)) { + System.err.println("Rejecting stream " + streamid + + " and sending GOAWAY on server connection " + + connKey + ", for request: " + path); + sendGoAway(ErrorFrame.NO_ERROR); + return; + } Queue q = new Queue(sentinel); streams.put(streamid, q); + // keep track of the largest request id that we have processed + int currentLargest = maxProcessedRequestStreamId.get(); + while (streamid > currentLargest) { + if (maxProcessedRequestStreamId.compareAndSet(currentLargest, streamid)) { + break; + } + currentLargest = maxProcessedRequestStreamId.get(); + } exec.submit(() -> { handleRequest(headers, q, streamid, endStreamReceived); }); @@ -763,6 +830,8 @@ void readLoop() { while (!stopping) { Http2Frame frame = readFrameImpl(); if (frame == null) { + System.err.println("EOF reached on connection " + connectionKey() + + ", will no longer accept incoming frames"); closeIncoming(); return; } @@ -786,6 +855,17 @@ void readLoop() { // TODO: close connection continue; } else { + final int streamId = frame.streamid(); + final int finalProcessedStreamId = goAwayRequestStreamId.get(); + // if we already sent a goaway, then don't create new streams with + // higher stream ids. + if (finalProcessedStreamId != -1 && streamId > finalProcessedStreamId) { + System.err.println(connectionKey() + " resetting stream " + streamId + + " as REFUSED_STREAM"); + final ResetFrame rst = new ResetFrame(streamId, REFUSED_STREAM); + outputQ.put(rst); + continue; + } createStream((HeadersFrame) frame); } } else { From 3dd07b91bbf644aa867452806e9388089fa97548 Mon Sep 17 00:00:00 2001 From: Qizheng Xing Date: Wed, 14 Aug 2024 06:28:34 +0000 Subject: [PATCH 70/84] 8336163: Remove declarations of some debug-only methods in release build Reviewed-by: dholmes, eliu, kvn --- src/hotspot/share/cds/heapShared.hpp | 4 ++++ src/hotspot/share/compiler/compilationPolicy.hpp | 2 ++ src/hotspot/share/opto/node.hpp | 2 ++ src/hotspot/share/runtime/frame.hpp | 6 ++++++ src/hotspot/share/runtime/registerMap.hpp | 10 +++++----- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index fa34289a38e..2c87b050ca6 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -371,7 +371,9 @@ class HeapShared: AllStatic { KlassSubGraphInfo* subgraph_info, oop orig_obj); +#ifndef PRODUCT static ResourceBitMap calculate_oopmap(MemRegion region); // marks all the oop pointers +#endif static void add_to_dumped_interned_strings(oop string); // Scratch objects for archiving Klass::java_mirror() @@ -426,7 +428,9 @@ class HeapShared: AllStatic { static void init_roots(oop roots_oop) NOT_CDS_JAVA_HEAP_RETURN; static void serialize_tables(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; +#ifndef PRODUCT static bool is_a_test_class_in_unnamed_module(Klass* ik) NOT_CDS_JAVA_HEAP_RETURN_(false); +#endif }; #if INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/compiler/compilationPolicy.hpp b/src/hotspot/share/compiler/compilationPolicy.hpp index 3ec60cd89c7..fe33fb8cfba 100644 --- a/src/hotspot/share/compiler/compilationPolicy.hpp +++ b/src/hotspot/share/compiler/compilationPolicy.hpp @@ -179,8 +179,10 @@ class CompilationPolicy : AllStatic { // Set carry flags in the counters (in Method* and MDO). inline static void handle_counter_overflow(const methodHandle& method); +#ifdef ASSERT // Verify that a level is consistent with the compilation mode static bool verify_level(CompLevel level); +#endif // Clamp the request level according to various constraints. inline static CompLevel limit_level(CompLevel level); // Common transition function. Given a predicate determines if a method should transition to another level. diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 10e1e7b1006..3e39e1ed2fb 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -834,7 +834,9 @@ class Node { juint _class_id; juint _flags; +#ifdef ASSERT static juint max_flags(); +#endif protected: // These methods should be called from constructors only. diff --git a/src/hotspot/share/runtime/frame.hpp b/src/hotspot/share/runtime/frame.hpp index 4113360724d..468437a6484 100644 --- a/src/hotspot/share/runtime/frame.hpp +++ b/src/hotspot/share/runtime/frame.hpp @@ -387,7 +387,9 @@ class frame { static int interpreter_frame_monitor_size(); static int interpreter_frame_monitor_size_in_bytes(); +#ifdef ASSERT void interpreter_frame_verify_monitor(BasicObjectLock* value) const; +#endif // Return/result value from this interpreter frame // If the method return type is T_OBJECT or T_ARRAY populates oop_result @@ -438,8 +440,10 @@ class frame { void print_on_error(outputStream* st, char* buf, int buflen, bool verbose = false) const; static void print_C_frame(outputStream* st, char* buf, int buflen, address pc); +#ifndef PRODUCT // Add annotated descriptions of memory locations belonging to this frame to values void describe(FrameValues& values, int frame_no, const RegisterMap* reg_map=nullptr); +#endif // Conversion from a VMReg to physical stack location template @@ -492,9 +496,11 @@ class frame { // Verification void verify(const RegisterMap* map) const; +#ifdef ASSERT static bool verify_return_pc(address x); // Usage: // assert(frame::verify_return_pc(return_address), "must be a return pc"); +#endif #include CPU_HEADER(frame) diff --git a/src/hotspot/share/runtime/registerMap.hpp b/src/hotspot/share/runtime/registerMap.hpp index 5cf68a87b71..a63a25cbb35 100644 --- a/src/hotspot/share/runtime/registerMap.hpp +++ b/src/hotspot/share/runtime/registerMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,19 +153,19 @@ class RegisterMap : public StackObj { const RegisterMap* as_RegisterMap() const { return this; } RegisterMap* as_RegisterMap() { return this; } +#ifndef PRODUCT void print_on(outputStream* st) const; void print() const; - void set_async(bool value) { NOT_PRODUCT(_async = value;) } - void set_skip_missing(bool value) { NOT_PRODUCT(_skip_missing = value;) } - -#ifndef PRODUCT bool is_async() const { return _async; } bool should_skip_missing() const { return _skip_missing; } VMReg find_register_spilled_here(void* p, intptr_t* sp); #endif + void set_async(bool value) { NOT_PRODUCT(_async = value;) } + void set_skip_missing(bool value) { NOT_PRODUCT(_skip_missing = value;) } + // the following contains the definition of pd_xxx methods #include CPU_HEADER(registerMap) From 66bee2532f849cfb7ab63857ecd7d773c2566722 Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Wed, 14 Aug 2024 09:13:21 +0000 Subject: [PATCH 71/84] 8338315: G1: G1CardTableEntryClosure:do_card_ptr remove unused parameter worker_id Reviewed-by: tschatzl --- src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp | 4 ++-- src/hotspot/share/gc/g1/g1RemSet.cpp | 4 ++-- src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp b/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp index 8fe0d7752eb..e2b53d69e06 100644 --- a/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp +++ b/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp @@ -36,7 +36,7 @@ class G1CardTableEntryClosure: public CHeapObj { typedef CardTable::CardValue CardValue; // Process the card whose card table entry is "card_ptr". - virtual void do_card_ptr(CardValue* card_ptr, uint worker_id) = 0; + virtual void do_card_ptr(CardValue* card_ptr) = 0; // Process all the card_ptrs in node. void apply_to_buffer(BufferNode* node, uint worker_id) { @@ -44,7 +44,7 @@ class G1CardTableEntryClosure: public CHeapObj { size_t capacity = node->capacity(); for (size_t i = node->index(); i < capacity; ++i) { CardValue* card_ptr = static_cast(buffer[i]); - do_card_ptr(card_ptr, worker_id); + do_card_ptr(card_ptr); } } }; diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index f2426cdfca5..0f9b9d17df7 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1230,11 +1230,10 @@ class G1MergeHeapRootsTask : public WorkerTask { _cards_skipped(0) {} - void do_card_ptr(CardValue* card_ptr, uint worker_id) { + void do_card_ptr(CardValue* card_ptr) override { // The only time we care about recording cards that // contain references that point into the collection set // is during RSet updating within an evacuation pause. - // In this case worker_id should be the id of a GC worker thread. assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); uint const region_idx = _ct->region_idx_for(card_ptr); @@ -1342,6 +1341,7 @@ class G1MergeHeapRootsTask : public WorkerTask { FREE_C_HEAP_ARRAY(Stack, _dirty_card_buffers); } } + virtual void work(uint worker_id) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1GCPhaseTimes* p = g1h->phase_times(); diff --git a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp index c5ebdb3d22d..e1f0df05c22 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp @@ -522,7 +522,7 @@ class RedirtyLoggedCardTableEntryClosure : public G1CardTableEntryClosure { _g1_ct(g1h->card_table()), _evac_failure_regions(evac_failure_regions) { } - void do_card_ptr(CardValue* card_ptr, uint worker_id) { + void do_card_ptr(CardValue* card_ptr) override { G1HeapRegion* hr = region_for_card(card_ptr); // Should only dirty cards in regions that won't be freed. From 9fe1777fafca30cf60acb5402c7c70800137136e Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 14 Aug 2024 09:16:02 +0000 Subject: [PATCH 72/84] 8338280: Parallel: Inline ParallelCompactData::verify_clear Reviewed-by: tschatzl --- src/hotspot/share/gc/parallel/psParallelCompact.cpp | 11 +++-------- src/hotspot/share/gc/parallel/psParallelCompact.hpp | 1 - 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 4d54f11805a..4bff8f8a7d0 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -521,19 +521,14 @@ bool ParallelCompactData::summarize(SplitInfo& split_info, } #ifdef ASSERT -void ParallelCompactData::verify_clear(const PSVirtualSpace* vspace) +void ParallelCompactData::verify_clear() { - const size_t* const beg = (const size_t*)vspace->committed_low_addr(); - const size_t* const end = (const size_t*)vspace->committed_high_addr(); + const size_t* const beg = (const size_t*) _region_vspace->committed_low_addr(); + const size_t* const end = (const size_t*) _region_vspace->committed_high_addr(); for (const size_t* p = beg; p < end; ++p) { assert(*p == 0, "not zero"); } } - -void ParallelCompactData::verify_clear() -{ - verify_clear(_region_vspace); -} #endif // #ifdef ASSERT STWGCTimer PSParallelCompact::_gc_timer; diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 1e04beb8c66..7e71f077223 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -393,7 +393,6 @@ class ParallelCompactData inline bool is_region_aligned(HeapWord* addr) const; #ifdef ASSERT - void verify_clear(const PSVirtualSpace* vspace); void verify_clear(); #endif // #ifdef ASSERT From 38bd8a36704a962f0ad1052fd2ec150a61663256 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 14 Aug 2024 09:52:23 +0000 Subject: [PATCH 73/84] 8338236: Compile error in cgroup code on Linux when using clang Reviewed-by: mdoerr, sgehwolf --- src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp | 4 ++-- src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index 251fbde85f0..56af87881e7 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ class CgroupV1Controller: public CgroupController { void set_subsystem_path(char *cgroup_path); char *subsystem_path() override { return _path; } - bool is_read_only() { return _read_only; } + bool is_read_only() override { return _read_only; } }; class CgroupV1MemoryController final : public CgroupMemoryController { diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index 02774fb70ae..cd100f29874 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Red Hat Inc. + * Copyright (c) 2020, 2024, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,8 +128,8 @@ class CgroupV2Subsystem: public CgroupSubsystem { const char * container_type() override { return "cgroupv2"; } - CachingCgroupController* memory_controller() { return _memory; } - CachingCgroupController* cpu_controller() { return _cpu; } + CachingCgroupController* memory_controller() override { return _memory; } + CachingCgroupController* cpu_controller() override { return _cpu; } }; #endif // CGROUP_V2_SUBSYSTEM_LINUX_HPP From fbe4f05636c8f692bd40bbe11fb5bb8b77b77042 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 14 Aug 2024 12:20:17 +0000 Subject: [PATCH 74/84] 8337976: Insufficient error recovery in parser for switch inside class body Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Attr.java | 13 +++- .../sun/tools/javac/parser/JavacParser.java | 22 +++++- .../sun/tools/javac/parser/VirtualParser.java | 2 +- .../tools/javac/resources/compiler.properties | 3 + .../diags/examples/StatementNotExpected.java | 28 +++++++ .../tools/javac/parser/JavacParserTest.java | 78 ++++++++++++++++++- .../javac/records/RecordCompilationTests.java | 2 +- .../tools/javac/recovery/T8337976.java | 10 +++ .../tools/javac/recovery/T8337976.out | 5 ++ 9 files changed, 156 insertions(+), 7 deletions(-) create mode 100644 test/langtools/tools/javac/diags/examples/StatementNotExpected.java create mode 100644 test/langtools/tools/javac/recovery/T8337976.java create mode 100644 test/langtools/tools/javac/recovery/T8337976.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 9b79846ba40..54edc19560b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -5251,7 +5251,18 @@ public void visitAnnotatedType(JCAnnotatedType tree) { public void visitErroneous(JCErroneous tree) { if (tree.errs != null) { - Env errEnv = env.dup(env.tree, env.info.dup()); + WriteableScope newScope = env.info.scope; + + if (env.tree instanceof JCClassDecl) { + Symbol fakeOwner = + new MethodSymbol(BLOCK, names.empty, null, + env.info.scope.owner); + newScope = newScope.dupUnshared(fakeOwner); + } + + Env errEnv = + env.dup(env.tree, + env.info.dup(newScope)); errEnv.info.returnResult = unknownExprInfo; for (JCTree err : tree.errs) attribTree(err, errEnv, new ResultInfo(KindSelector.ERR, pt())); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index f570ad54c58..6fc93fdc591 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -455,7 +455,7 @@ protected JCErroneous syntaxError(int pos, Error errorKey) { return syntaxError(pos, List.nil(), errorKey); } - protected JCErroneous syntaxError(int pos, List errs, Error errorKey) { + protected JCErroneous syntaxError(int pos, List errs, Error errorKey) { setErrorEndPos(pos); JCErroneous err = F.at(pos).Erroneous(errs); reportSyntaxError(err, errorKey); @@ -4733,6 +4733,12 @@ protected List classOrInterfaceOrRecordBodyDeclaration(JCModifiers mods, } ignoreDanglingComments(); // no declaration with which dangling comments can be associated return List.of(block(pos, mods.flags)); + } else if (isDefiniteStatementStartToken()) { + int startPos = token.pos; + List statements = blockStatement(); + return List.of(syntaxError(startPos, + statements, + Errors.StatementNotExpected)); } else { return constructorOrMethodOrFieldDeclaration(mods, className, isInterface, isRecord, dc); } @@ -4910,7 +4916,19 @@ protected boolean isDeclaration() { token.kind == INTERFACE || token.kind == ENUM || isRecordStart() && allowRecords; - } + } + + /** + * {@return true if and only if the current token is definitelly a token that + * starts a statement.} + */ + private boolean isDefiniteStatementStartToken() { + return switch (token.kind) { + case IF, WHILE, DO, SWITCH, RETURN, TRY, FOR, ASSERT, BREAK, + CONTINUE, THROW -> true; + default -> false; + }; + } protected boolean isRecordStart() { if (token.kind == IDENTIFIER && token.name() == names.record && peekToken(TokenKind.IDENTIFIER)) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java index f32c1bf4756..ec3a373ab4e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java @@ -62,7 +62,7 @@ protected JCErroneous syntaxError(int pos, Error errorKey) { } @Override - protected JCErroneous syntaxError(int pos, List errs, Error errorKey) { + protected JCErroneous syntaxError(int pos, List errs, Error errorKey) { hasErrors = true; return F.Erroneous(); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 10f06ad7017..6fd59438220 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1616,6 +1616,9 @@ compiler.err.file.sb.on.source.or.patch.path.for.module=\ compiler.err.no.java.lang=\ Unable to find package java.lang in platform classes +compiler.err.statement.not.expected=\ + statements not expected outside of methods and initializers + ##### # Fatal Errors diff --git a/test/langtools/tools/javac/diags/examples/StatementNotExpected.java b/test/langtools/tools/javac/diags/examples/StatementNotExpected.java new file mode 100644 index 00000000000..a6b965a8044 --- /dev/null +++ b/test/langtools/tools/javac/diags/examples/StatementNotExpected.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.statement.not.expected + +class StatementNotExpected { + return null; +} diff --git a/test/langtools/tools/javac/parser/JavacParserTest.java b/test/langtools/tools/javac/parser/JavacParserTest.java index 93b2b51a8fa..547de1088b4 100644 --- a/test/langtools/tools/javac/parser/JavacParserTest.java +++ b/test/langtools/tools/javac/parser/JavacParserTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041 8253584 8246774 8256411 8256149 8259050 8266436 8267221 8271928 8275097 8293897 8295401 8304671 8310326 8312093 8312204 8315452 + * @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041 8253584 8246774 8256411 8256149 8259050 8266436 8267221 8271928 8275097 8293897 8295401 8304671 8310326 8312093 8312204 8315452 8337976 * @summary tests error and diagnostics positions * @author Jan Lahoda * @modules jdk.compiler/com.sun.tools.javac.api @@ -2409,6 +2409,80 @@ void testPartialTopLevelModifiers() throws IOException { (ERROR: public )"""); } + @Test //JDK-8337976 + void testStatementsInClass() throws IOException { + String code = """ + package test; + public class Test { + if (true); + while (true); + do {} while (true); + for ( ; ; ); + switch (0) { default: } + assert true; + break; + continue; + return ; + throw new RuntimeException(); + try { + } catch (RuntimeException ex) {} + } + """; + DiagnosticCollector coll = + new DiagnosticCollector<>(); + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, + List.of("--enable-preview", "--source", SOURCE_VERSION), + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + + String result = toStringWithErrors(cut).replaceAll("\\R", "\n"); + System.out.println("RESULT\n" + result); + assertEquals("incorrect AST", + result, + """ + package test; + \n\ + public class Test { + (ERROR: if (true) ;) + (ERROR: while (true) ;) + (ERROR: do { + } while (true);) + (ERROR: for (; ; ) ;) + (ERROR: switch (0) { + default: + + }) + (ERROR: assert true;) + (ERROR: break;) + (ERROR: continue;) + (ERROR: return;) + (ERROR: throw new RuntimeException();) + (ERROR: try { + } catch (RuntimeException ex) { + }) + }"""); + + List codes = new LinkedList<>(); + + for (Diagnostic d : coll.getDiagnostics()) { + codes.add(d.getLineNumber() + ":" + d.getColumnNumber() + ":" + d.getCode()); + } + + assertEquals("testStatementsInClass: " + codes, + List.of("3:5:compiler.err.statement.not.expected", + "4:5:compiler.err.statement.not.expected", + "5:5:compiler.err.statement.not.expected", + "6:5:compiler.err.statement.not.expected", + "7:5:compiler.err.statement.not.expected", + "8:5:compiler.err.statement.not.expected", + "9:5:compiler.err.statement.not.expected", + "10:5:compiler.err.statement.not.expected", + "11:5:compiler.err.statement.not.expected", + "12:5:compiler.err.statement.not.expected", + "13:5:compiler.err.statement.not.expected"), + codes); + } + void run(String[] args) throws Exception { int passed = 0, failed = 0; final Pattern p = (args != null && args.length > 0) diff --git a/test/langtools/tools/javac/records/RecordCompilationTests.java b/test/langtools/tools/javac/records/RecordCompilationTests.java index cbd00f9c607..d80ade50a3b 100644 --- a/test/langtools/tools/javac/records/RecordCompilationTests.java +++ b/test/langtools/tools/javac/records/RecordCompilationTests.java @@ -1358,7 +1358,7 @@ void testAcceptRecordId() { try { String[] testOptions = {}; setCompileOptions(testOptions); - assertFail("compiler.err.illegal.start.of.type", + assertFail("compiler.err.statement.not.expected", "class R {\n" + " record RR(int i) {\n" + " return null;\n" + diff --git a/test/langtools/tools/javac/recovery/T8337976.java b/test/langtools/tools/javac/recovery/T8337976.java new file mode 100644 index 00000000000..cac987f4083 --- /dev/null +++ b/test/langtools/tools/javac/recovery/T8337976.java @@ -0,0 +1,10 @@ +/** + * @test /nodynamiccopyright/ + * @bug 8337976 + * @summary Verify javac does not crash and produces nice errors for certain erroneous code. + * @compile/fail/ref=T8337976.out -XDrawDiagnostics -XDshould-stop.at=FLOW -XDdev T8337976.java + */ +public class T8337976 { + switch (0) { default: undefined u;} + if (true) { undefined u; } +} diff --git a/test/langtools/tools/javac/recovery/T8337976.out b/test/langtools/tools/javac/recovery/T8337976.out new file mode 100644 index 00000000000..bae578cecf3 --- /dev/null +++ b/test/langtools/tools/javac/recovery/T8337976.out @@ -0,0 +1,5 @@ +T8337976.java:8:5: compiler.err.statement.not.expected +T8337976.java:9:5: compiler.err.statement.not.expected +T8337976.java:8:27: compiler.err.cant.resolve.location: kindname.class, undefined, , , (compiler.misc.location: kindname.class, T8337976, null) +T8337976.java:9:17: compiler.err.cant.resolve.location: kindname.class, undefined, , , (compiler.misc.location: kindname.class, T8337976, null) +4 errors From a5d948fb9841f654cccc9567c60e8d28e7d719ae Mon Sep 17 00:00:00 2001 From: John Engebretson Date: Wed, 14 Aug 2024 14:11:53 +0000 Subject: [PATCH 75/84] 8332842: Optimize empty CopyOnWriteArrayList allocations Reviewed-by: shade, alanb --- .../util/concurrent/CopyOnWriteArrayList.java | 22 ++- .../CopyOnWriteArrayListBenchmark.java | 166 ++++++++++++++++++ 2 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/util/concurrent/CopyOnWriteArrayListBenchmark.java diff --git a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index 7182f98706d..f0f60730eb6 100644 --- a/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -100,6 +100,8 @@ public class CopyOnWriteArrayList implements List, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8673264195747942595L; + private static final Object[] EMPTY_ELEMENTDATA = {}; + /** * The lock protecting all mutators. (We have a mild preference * for builtin monitors over ReentrantLock when either will do.) @@ -128,7 +130,7 @@ final void setArray(Object[] a) { * Creates an empty list. */ public CopyOnWriteArrayList() { - setArray(new Object[0]); + setArray(EMPTY_ELEMENTDATA); } /** @@ -143,6 +145,8 @@ public CopyOnWriteArrayList(Collection c) { Object[] es; if (c.getClass() == CopyOnWriteArrayList.class) es = ((CopyOnWriteArrayList)c).getArray(); + else if (c.isEmpty()) + es = EMPTY_ELEMENTDATA; else { es = c.toArray(); if (c.getClass() != java.util.ArrayList.class) @@ -159,7 +163,10 @@ public CopyOnWriteArrayList(Collection c) { * @throws NullPointerException if the specified array is null */ public CopyOnWriteArrayList(E[] toCopyIn) { - setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class)); + if (toCopyIn.length == 0) + setArray(EMPTY_ELEMENTDATA); + else + setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class)); } /** @@ -533,6 +540,8 @@ public E remove(int index) { Object[] newElements; if (numMoved == 0) newElements = Arrays.copyOf(es, len - 1); + else if (len == 1) + newElements = EMPTY_ELEMENTDATA; else { newElements = new Object[len - 1]; System.arraycopy(es, 0, newElements, 0, index); @@ -618,6 +627,11 @@ private boolean remove(Object o, Object[] snapshot, int index) { if (index < 0) return false; } + if (len == 1) { + // one element exists and that element should be removed + setArray(EMPTY_ELEMENTDATA); + return true; + } Object[] newElements = new Object[len - 1]; System.arraycopy(current, 0, newElements, 0, index); System.arraycopy(current, index + 1, @@ -804,7 +818,7 @@ public int addAllAbsent(Collection c) { */ public void clear() { synchronized (lock) { - setArray(new Object[0]); + setArray(EMPTY_ELEMENTDATA); } } @@ -1022,7 +1036,7 @@ private void readObject(java.io.ObjectInputStream s) // Read in array length and allocate array int len = s.readInt(); SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, len); - Object[] es = new Object[len]; + Object[] es = (len == 0 ? EMPTY_ELEMENTDATA : new Object[len]); // Read in all elements in the proper order. for (int i = 0; i < len; i++) diff --git a/test/micro/org/openjdk/bench/java/util/concurrent/CopyOnWriteArrayListBenchmark.java b/test/micro/org/openjdk/bench/java/util/concurrent/CopyOnWriteArrayListBenchmark.java new file mode 100644 index 00000000000..0ce091d1724 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/concurrent/CopyOnWriteArrayListBenchmark.java @@ -0,0 +1,166 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.java.util.concurrent; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Benchmark) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(1) +@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +public class CopyOnWriteArrayListBenchmark { + + private static byte[] getSerializedBytes(CopyOnWriteArrayList list) throws IOException { + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + ObjectOutputStream objectOut = new ObjectOutputStream(bytesOut); + objectOut.writeObject(list); + + objectOut.close(); + return bytesOut.toByteArray(); + } + + private Collection emptyCollection = new ArrayList<>(); + private Object[] emptyArray = new Object[0]; + + private Collection oneItemCollection = Arrays.asList(""); + private Object[] oneItemArray = new Object[] { "" }; + + private CopyOnWriteArrayList emptyInstance = new CopyOnWriteArrayList<>(); + private CopyOnWriteArrayList oneItemInstance = new CopyOnWriteArrayList<>(oneItemArray); + + private byte[] emptyInstanceBytes; + private byte[] oneInstanceBytes; + + public CopyOnWriteArrayListBenchmark() { + try { + emptyInstanceBytes = getSerializedBytes(emptyInstance); + oneInstanceBytes = getSerializedBytes(oneItemInstance); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Benchmark + public void clear() { + // have to create a new instance on each execution + ((CopyOnWriteArrayList) oneItemInstance.clone()).clear(); + } + + @Benchmark + public void clearEmpty() { + emptyInstance.clear(); + } + + @Benchmark + public CopyOnWriteArrayList createInstanceArray() { + return new CopyOnWriteArrayList<>(oneItemArray); + } + + @Benchmark + public CopyOnWriteArrayList createInstanceArrayEmpty() { + return new CopyOnWriteArrayList<>(emptyArray); + } + + @Benchmark + public CopyOnWriteArrayList createInstanceCollection() { + return new CopyOnWriteArrayList<>(oneItemCollection); + } + + @Benchmark + public CopyOnWriteArrayList createInstanceCollectionEmpty() { + return new CopyOnWriteArrayList<>(emptyCollection); + } + + @Benchmark + public CopyOnWriteArrayList createInstanceDefault() { + return new CopyOnWriteArrayList(); + } + + @Benchmark + public CopyOnWriteArrayList readInstance() throws IOException, ClassNotFoundException { + try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(oneInstanceBytes))) { + return (CopyOnWriteArrayList) objIn.readObject(); + } + } + + @Benchmark + public CopyOnWriteArrayList readInstanceEmpty() throws IOException, ClassNotFoundException { + try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(emptyInstanceBytes))) { + return (CopyOnWriteArrayList) objIn.readObject(); + } + } + + @Benchmark + public CopyOnWriteArrayList removeObjectLastRemaining() { + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); + list.add(""); + list.remove(""); + return list; + } + + @Benchmark + public CopyOnWriteArrayList removeIndexLastRemaining() { + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); + list.add(""); + list.remove(0); + return list; + } + @Benchmark + public CopyOnWriteArrayList removeObject() { + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); + list.add(""); + list.add("a"); + list.remove(""); + return list; + } + + @Benchmark + public CopyOnWriteArrayList remove() { + CopyOnWriteArrayList list = new CopyOnWriteArrayList<>(); + list.add(""); + list.add("a"); + list.remove(0); + return list; + } +} From d8e4d3f2d6c187f2487acd390a4e5fa2a99010ea Mon Sep 17 00:00:00 2001 From: Zdenek Zambersky Date: Wed, 14 Aug 2024 15:20:07 +0000 Subject: [PATCH 76/84] 8338402: GHA: some of bundles may not get removed Reviewed-by: ihse, shade --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b16335b7091..6a1b4420e3a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -371,7 +371,7 @@ jobs: -H 'Accept: application/vnd.github+json' \ -H 'Authorization: Bearer ${{ github.token }}' \ -H 'X-GitHub-Api-Version: 2022-11-28' \ - '${{ github.api_url }}/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts')" + '${{ github.api_url }}/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts?per_page=100')" BUNDLE_ARTIFACT_IDS="$(echo "$ALL_ARTIFACT_IDS" | jq -r -c '.artifacts | map(select(.name|startswith("bundles-"))) | .[].id')" for id in $BUNDLE_ARTIFACT_IDS; do echo "Removing $id" From 0e3903f2eb854715acee92cfc5ee2d4a2e800f61 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 14 Aug 2024 16:49:11 +0000 Subject: [PATCH 77/84] 8338393: Parallel: Remove unused ParallelCompactData::clear_range Reviewed-by: tschatzl --- src/hotspot/share/gc/parallel/psParallelCompact.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 7e71f077223..3f487ec3ef4 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -374,9 +374,6 @@ class ParallelCompactData HeapWord** target_next); void clear_range(size_t beg_region, size_t end_region); - void clear_range(HeapWord* beg, HeapWord* end) { - clear_range(addr_to_region_idx(beg), addr_to_region_idx(end)); - } // Return the number of words between addr and the start of the region // containing addr. From 6a390147959e0fb88de6ee13204cff72cd910f09 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 14 Aug 2024 16:56:28 +0000 Subject: [PATCH 78/84] 8338110: Exclude Fingerprinter::do_type from ubsan checks Reviewed-by: jwaters, rrich --- src/hotspot/share/runtime/signature.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hotspot/share/runtime/signature.hpp b/src/hotspot/share/runtime/signature.hpp index 3f7d062ab66..25de9c0a1f0 100644 --- a/src/hotspot/share/runtime/signature.hpp +++ b/src/hotspot/share/runtime/signature.hpp @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "oops/method.hpp" +#include "sanitizers/ub.hpp" // Static routines and parsing loops for processing field and method @@ -338,6 +339,7 @@ class Fingerprinter: public SignatureIterator { void do_type_calling_convention(BasicType type); friend class SignatureIterator; // so do_parameters_on can call do_type + ATTRIBUTE_NO_UBSAN void do_type(BasicType type) { assert(fp_is_valid_type(type), "bad parameter type"); _accumulator |= ((fingerprint_t)type << _shift_count); From c0384b6f3584501fb3bd93854734eeacf6620a7e Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 14 Aug 2024 17:58:24 +0000 Subject: [PATCH 79/84] 8337237: Use FFM instead of Unsafe for Java 2D RenderBuffer class Reviewed-by: jvernee, jdv --- .../classes/sun/java2d/pipe/RenderBuffer.java | 134 ++++++++---------- 1 file changed, 60 insertions(+), 74 deletions(-) diff --git a/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java b/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java index 57f24a4eada..2b57d98ef40 100644 --- a/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java +++ b/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,58 +25,54 @@ package sun.java2d.pipe; -import jdk.internal.misc.Unsafe; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import static java.lang.foreign.ValueLayout.*; /** - * The RenderBuffer class is a simplified, high-performance, Unsafe wrapper + * The RenderBuffer class is a simplified, high-performance class * used for buffering rendering operations in a single-threaded rendering - * environment. It's functionality is similar to the ByteBuffer and related + * environment. Its functionality is similar to the ByteBuffer and related * NIO classes. However, the methods in this class perform little to no * alignment or bounds checks for performance reasons. Therefore, it is * the caller's responsibility to ensure that all put() calls are properly * aligned and within bounds: * - int and float values must be aligned on 4-byte boundaries * - long and double values must be aligned on 8-byte boundaries + * Failure to do so will result in exceptions from the FFM API, or worse. * * This class only includes the bare minimum of methods to support * single-threaded rendering. For example, there is no put(double[]) method * because we currently have no need for such a method in the STR classes. */ -public class RenderBuffer { +public final class RenderBuffer { /** * These constants represent the size of various data types (in bytes). */ - protected static final long SIZEOF_BYTE = 1L; - protected static final long SIZEOF_SHORT = 2L; - protected static final long SIZEOF_INT = 4L; - protected static final long SIZEOF_FLOAT = 4L; - protected static final long SIZEOF_LONG = 8L; - protected static final long SIZEOF_DOUBLE = 8L; + private static final int SIZEOF_BYTE = Byte.BYTES; + private static final int SIZEOF_SHORT = Short.BYTES; + private static final int SIZEOF_INT = Integer.BYTES; + private static final int SIZEOF_FLOAT = Float.BYTES; + private static final int SIZEOF_LONG = Long.BYTES; + private static final int SIZEOF_DOUBLE = Double.BYTES; /** - * Represents the number of elements at which we have empirically - * determined that the average cost of a JNI call exceeds the expense - * of an element by element copy. In other words, if the number of - * elements in an array to be copied exceeds this value, then we should - * use the copyFromArray() method to complete the bulk put operation. - * (This value can be adjusted if the cost of JNI downcalls is reduced - * in a future release.) + * Measurements show that using the copy API from a segment backed by a heap + * array gets reliably faster than individual puts around a length of 10. + * However the time is miniscule in the context of what it is used for + * and much more than adequate, so no problem expected if this changes over time. */ - private static final int COPY_FROM_ARRAY_THRESHOLD = 6; - - protected final Unsafe unsafe; - protected final long baseAddress; - protected final long endAddress; - protected long curAddress; - protected final int capacity; - - protected RenderBuffer(int numBytes) { - unsafe = Unsafe.getUnsafe(); - curAddress = baseAddress = unsafe.allocateMemory(numBytes); - endAddress = baseAddress + numBytes; - capacity = numBytes; + private static final int COPY_FROM_ARRAY_THRESHOLD = 10; + + private final MemorySegment segment; + private int curOffset; + + private RenderBuffer(int numBytes) { + segment = Arena.global().allocate(numBytes, SIZEOF_DOUBLE); + curOffset = 0; } /** @@ -90,7 +86,7 @@ public static RenderBuffer allocate(int numBytes) { * Returns the base address of the underlying memory buffer. */ public final long getAddress() { - return baseAddress; + return segment.address(); } /** @@ -99,27 +95,27 @@ public final long getAddress() { */ public final int capacity() { - return capacity; + return (int)segment.byteSize(); } public final int remaining() { - return (int)(endAddress - curAddress); + return (capacity() - curOffset); } public final int position() { - return (int)(curAddress - baseAddress); + return curOffset; } - public final void position(long numBytes) { - curAddress = baseAddress + numBytes; + public final void position(int bytePos) { + curOffset = bytePos; } public final void clear() { - curAddress = baseAddress; + curOffset = 0; } - public final RenderBuffer skip(long numBytes) { - curAddress += numBytes; + public final RenderBuffer skip(int numBytes) { + curOffset += numBytes; return this; } @@ -128,8 +124,8 @@ public final RenderBuffer skip(long numBytes) { */ public final RenderBuffer putByte(byte x) { - unsafe.putByte(curAddress, x); - curAddress += SIZEOF_BYTE; + segment.set(JAVA_BYTE, curOffset, x); + curOffset += SIZEOF_BYTE; return this; } @@ -139,10 +135,8 @@ public RenderBuffer put(byte[] x) { public RenderBuffer put(byte[] x, int offset, int length) { if (length > COPY_FROM_ARRAY_THRESHOLD) { - long offsetInBytes = offset * SIZEOF_BYTE + Unsafe.ARRAY_BYTE_BASE_OFFSET; - long lengthInBytes = length * SIZEOF_BYTE; - unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes); - position(position() + lengthInBytes); + MemorySegment.copy(x, offset, segment, JAVA_BYTE, curOffset, length); + position(position() + length * SIZEOF_BYTE); } else { int end = offset + length; for (int i = offset; i < end; i++) { @@ -158,8 +152,8 @@ public RenderBuffer put(byte[] x, int offset, int length) { public final RenderBuffer putShort(short x) { // assert (position() % SIZEOF_SHORT == 0); - unsafe.putShort(curAddress, x); - curAddress += SIZEOF_SHORT; + segment.set(JAVA_SHORT, curOffset, x); + curOffset += SIZEOF_SHORT; return this; } @@ -170,10 +164,8 @@ public RenderBuffer put(short[] x) { public RenderBuffer put(short[] x, int offset, int length) { // assert (position() % SIZEOF_SHORT == 0); if (length > COPY_FROM_ARRAY_THRESHOLD) { - long offsetInBytes = offset * SIZEOF_SHORT + Unsafe.ARRAY_SHORT_BASE_OFFSET; - long lengthInBytes = length * SIZEOF_SHORT; - unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes); - position(position() + lengthInBytes); + MemorySegment.copy(x, offset, segment, JAVA_SHORT, curOffset, length); + position(position() + length * SIZEOF_SHORT); } else { int end = offset + length; for (int i = offset; i < end; i++) { @@ -188,15 +180,15 @@ public RenderBuffer put(short[] x, int offset, int length) { */ public final RenderBuffer putInt(int pos, int x) { - // assert (baseAddress + pos % SIZEOF_INT == 0); - unsafe.putInt(baseAddress + pos, x); + // assert (getAddress() + pos % SIZEOF_INT == 0); + segment.set(JAVA_INT, pos, x); return this; } public final RenderBuffer putInt(int x) { // assert (position() % SIZEOF_INT == 0); - unsafe.putInt(curAddress, x); - curAddress += SIZEOF_INT; + segment.set(JAVA_INT, curOffset, x); + curOffset += SIZEOF_INT; return this; } @@ -207,10 +199,8 @@ public RenderBuffer put(int[] x) { public RenderBuffer put(int[] x, int offset, int length) { // assert (position() % SIZEOF_INT == 0); if (length > COPY_FROM_ARRAY_THRESHOLD) { - long offsetInBytes = offset * SIZEOF_INT + Unsafe.ARRAY_INT_BASE_OFFSET; - long lengthInBytes = length * SIZEOF_INT; - unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes); - position(position() + lengthInBytes); + MemorySegment.copy(x, offset, segment, JAVA_INT, curOffset, length); + position(position() + length * SIZEOF_INT); } else { int end = offset + length; for (int i = offset; i < end; i++) { @@ -226,8 +216,8 @@ public RenderBuffer put(int[] x, int offset, int length) { public final RenderBuffer putFloat(float x) { // assert (position() % SIZEOF_FLOAT == 0); - unsafe.putFloat(curAddress, x); - curAddress += SIZEOF_FLOAT; + segment.set(JAVA_FLOAT, curOffset, x); + curOffset += SIZEOF_FLOAT; return this; } @@ -238,10 +228,8 @@ public RenderBuffer put(float[] x) { public RenderBuffer put(float[] x, int offset, int length) { // assert (position() % SIZEOF_FLOAT == 0); if (length > COPY_FROM_ARRAY_THRESHOLD) { - long offsetInBytes = offset * SIZEOF_FLOAT + Unsafe.ARRAY_FLOAT_BASE_OFFSET; - long lengthInBytes = length * SIZEOF_FLOAT; - unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes); - position(position() + lengthInBytes); + MemorySegment.copy(x, offset, segment, JAVA_FLOAT, curOffset, length); + position(position() + length * SIZEOF_FLOAT); } else { int end = offset + length; for (int i = offset; i < end; i++) { @@ -257,8 +245,8 @@ public RenderBuffer put(float[] x, int offset, int length) { public final RenderBuffer putLong(long x) { // assert (position() % SIZEOF_LONG == 0); - unsafe.putLong(curAddress, x); - curAddress += SIZEOF_LONG; + segment.set(JAVA_LONG, curOffset, x); + curOffset += SIZEOF_LONG; return this; } @@ -269,10 +257,8 @@ public RenderBuffer put(long[] x) { public RenderBuffer put(long[] x, int offset, int length) { // assert (position() % SIZEOF_LONG == 0); if (length > COPY_FROM_ARRAY_THRESHOLD) { - long offsetInBytes = offset * SIZEOF_LONG + Unsafe.ARRAY_LONG_BASE_OFFSET; - long lengthInBytes = length * SIZEOF_LONG; - unsafe.copyMemory(x, offsetInBytes, null, curAddress, lengthInBytes); - position(position() + lengthInBytes); + MemorySegment.copy(x, offset, segment, JAVA_LONG, curOffset, length); + position(position() + length * SIZEOF_LONG); } else { int end = offset + length; for (int i = offset; i < end; i++) { @@ -288,8 +274,8 @@ public RenderBuffer put(long[] x, int offset, int length) { public final RenderBuffer putDouble(double x) { // assert (position() % SIZEOF_DOUBLE == 0); - unsafe.putDouble(curAddress, x); - curAddress += SIZEOF_DOUBLE; + segment.set(JAVA_DOUBLE, curOffset, x); + curOffset += SIZEOF_DOUBLE; return this; } } From 723ac5763aed0d67516c6746f39a066efc412b48 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 14 Aug 2024 18:41:24 +0000 Subject: [PATCH 80/84] 8332488: Add JVMTI DataDumpRequest to the debug agent Reviewed-by: sspitsyn, lmesnik --- .../share/native/libjdwp/debugInit.c | 11 +- .../share/native/libjdwp/eventFilter.c | 8 +- .../share/native/libjdwp/eventFilter.h | 6 +- .../share/native/libjdwp/eventHandler.c | 59 +++++- .../share/native/libjdwp/eventHandler.h | 4 +- .../share/native/libjdwp/threadControl.c | 13 +- .../share/native/libjdwp/threadControl.h | 4 +- .../share/native/libjdwp/util.c | 4 - .../share/native/libjdwp/util.h | 3 +- test/jdk/com/sun/jdi/DataDumpTest.java | 176 ++++++++++++++++++ 10 files changed, 251 insertions(+), 37 deletions(-) create mode 100644 test/jdk/com/sun/jdi/DataDumpTest.java diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c index fe990e97a65..b221cf6cf25 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -995,6 +995,8 @@ parseOptions(char *options) gdata->includeVThreads = JNI_FALSE; gdata->rememberVThreadsWhenDisconnected = JNI_FALSE; + gdata->jvmti_data_dump = JNI_FALSE; + /* Options being NULL will end up being an error. */ if (options == NULL) { options = ""; @@ -1159,6 +1161,13 @@ parseOptions(char *options) if ( dopause ) { do_pause(); } + } else if (strcmp(buf, "datadump") == 0) { + // Enable JVMTI DATA_DUMP_REQUEST support. + // This is not a documented flag. This feature is experimental and is only intended + // to be used by debug agent developers. See comment for cbDataDump() for more details. + if ( !get_boolean(&str, &(gdata->jvmti_data_dump)) ) { + goto syntax_error; + } } else if (strcmp(buf, "coredump") == 0) { if ( !get_boolean(&str, &docoredump) ) { goto syntax_error; diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.c b/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.c index af56d7145c9..3ba875e88cd 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1387,9 +1387,7 @@ eventFilterRestricted_deinstall(HandlerNode *node) return error1 != JVMTI_ERROR_NONE? error1 : error2; } -/***** debugging *****/ - -#ifdef DEBUG +/***** APIs for debugging the debug agent *****/ void eventFilter_dumpHandlerFilters(HandlerNode *node) @@ -1476,5 +1474,3 @@ eventFilter_dumpHandlerFilters(HandlerNode *node) } } } - -#endif /* DEBUG */ diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.h b/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.h index 9d79509f0d2..984d64815d6 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/eventFilter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,10 +76,8 @@ jvmtiError eventFilter_setPlatformThreadsOnlyFilter(HandlerNode *node, jint inde jboolean eventFilter_predictFiltering(HandlerNode *node, jclass clazz, char *classname); jboolean isBreakpointSet(jclass clazz, jmethodID method, jlocation location); -/***** debugging *****/ +/***** APIs for debugging the debug agent *****/ -#ifdef DEBUG void eventFilter_dumpHandlerFilters(HandlerNode *node); -#endif #endif /* _EVENT_FILTER_H */ diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c b/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c index cf2de806119..e4a9bd79943 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.c @@ -1330,6 +1330,44 @@ cbVMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) LOG_MISC(("END cbVMDeath")); } +/** + * Event callback for JVMTI_EVENT_DATA_DUMP_REQUEST + * + * This callback is made when a JVMTI data dump is requested. The common way of doing + * this is with "jcmd JVMTI.data_dump". + * + * Debug agent data dumps are experimental and only intended to be used by debug agent + * developers. Data dumps are disabled by default. + * + * This callback is enabled by launching the debug agent with datadump=y. The easiest + * way to enabled data dumps with debugger tests or when using jdb is to use the + * _JAVA_JDWP_OPTIONS export. The following works well when running tests: + * + * make test TEST= \ + * JTREG='JAVA_OPTIONS=-XX:+StartAttachListener;OPTIONS=-e:_JAVA_JDWP_OPTIONS=datadump=y' + * + * Data dumps may fail to happen due to the debug agent suspending all threads. + * This causes the Signal Dispatcher and Attach Listener threads to be suspended, + * which can cause issues with jcmd attaching. Running with -XX:+StartAttachListener can + * help, but in general it is best not to try a datadump when all threads are suspended. + * + * Data dumps are also risky when the debug agent is handling events or commands from + * the debugger, due to dumping data that is not lock protected. This can cause a + * crash. + * + * Data dumps are meant to aid with post mortem debugging (debugging after a + * problem has been detected), not for ongoing periodic data gathering. + */ +static void JNICALL +cbDataDump(jvmtiEnv *jvmti_env) +{ + tty_message("Debug Agent Data Dump"); + tty_message("=== START DUMP ==="); + threadControl_dumpAllThreads(); + eventHandler_dumpAllHandlers(JNI_TRUE); + tty_message("=== END DUMP ==="); +} + /** * Delete this handler (do not delete permanent handlers): * Deinsert handler from active list, @@ -1518,6 +1556,19 @@ eventHandler_initialize(jbyte sessionID) if (error != JVMTI_ERROR_NONE) { EXIT_ERROR(error,"Can't enable garbage collection finish events"); } + + /* + * DATA_DUMP_REQUEST is special since it is not tied to any handlers or an EI, + * so it cannot be setup using threadControl_setEventMode(). Use JVMTI API directly. + */ + if (gdata->jvmti_data_dump) { + error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode) + (gdata->jvmti, JVMTI_ENABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, NULL); + if (error != JVMTI_ERROR_NONE) { + EXIT_ERROR(error,"Can't enable data dump request events"); + } + } + /* * Only enable vthread START and END events if we want to remember * vthreads when no debugger is connected. @@ -1580,6 +1631,8 @@ eventHandler_initialize(jbyte sessionID) gdata->callbacks.VirtualThreadStart = &cbVThreadStart; /* Event callback for JVMTI_EVENT_VIRTUAL_THREAD_END */ gdata->callbacks.VirtualThreadEnd = &cbVThreadEnd; + /* Event callback for JVMTI_EVENT_DATA_DUMP_REQUEST */ + gdata->callbacks.DataDumpRequest = &cbDataDump; error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks) (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks)); @@ -1851,9 +1904,7 @@ eventHandler_installExternal(HandlerNode *node) JNI_TRUE); } -/***** debugging *****/ - -#ifdef DEBUG +/***** APIs for debugging the debug agent *****/ void eventHandler_dumpAllHandlers(jboolean dumpPermanent) @@ -1892,5 +1943,3 @@ eventHandler_dumpHandler(HandlerNode *node) tty_message("Handler for %s(%d)\n", eventIndex2EventName(node->ei), node->ei); eventFilter_dumpHandlerFilters(node); } - -#endif /* DEBUG */ diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.h b/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.h index 096b1ed795a..7d3684e6aa0 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/eventHandler.h @@ -85,12 +85,10 @@ jboolean eventHandler_synthesizeUnloadEvent(char *signature, JNIEnv *env); jclass getMethodClass(jvmtiEnv *jvmti_env, jmethodID method); -/***** debugging *****/ +/***** APIs for debugging the debug agent *****/ -#ifdef DEBUG void eventHandler_dumpAllHandlers(jboolean dumpPermanent); void eventHandler_dumpHandlers(EventIndex ei, jboolean dumpPermanent); void eventHandler_dumpHandler(HandlerNode *node); -#endif #endif /* _EVENTHANDLER_H */ diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c index 220e0040979..7e68e65e56c 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c @@ -137,11 +137,6 @@ typedef struct { static DeferredEventModeList deferredEventModes; -#ifdef DEBUG -static void dumpThreadList(ThreadList *list); -static void dumpThread(ThreadNode *node); -#endif - /* Get the state of the thread direct from JVMTI */ static jvmtiError threadState(jthread thread, jint *pstate) @@ -2561,13 +2556,15 @@ threadControl_allVThreads(jint *numVThreads) return vthreads; } -/***** debugging *****/ +/***** APIs for debugging the debug agent *****/ -#ifdef DEBUG +static void dumpThreadList(ThreadList *list); +static void dumpThread(ThreadNode *node); void threadControl_dumpAllThreads() { + tty_message("suspendAllCount: %d", suspendAllCount); tty_message("Dumping runningThreads:"); dumpThreadList(&runningThreads); tty_message("\nDumping runningVThreads:"); @@ -2652,5 +2649,3 @@ dumpThread(ThreadNode *node) { tty_message("\tobjID: %d", commonRef_refToID(getEnv(), node->thread)); #endif } - -#endif /* DEBUG */ diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.h b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.h index a314ed24bee..b7817d35981 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.h @@ -76,11 +76,9 @@ jlong threadControl_getFrameGeneration(jthread thread); jthread *threadControl_allVThreads(jint *numVThreads); -/***** debugging *****/ +/***** APIs for debugging the debug agent *****/ -#ifdef DEBUG void threadControl_dumpAllThreads(); void threadControl_dumpThread(jthread thread); -#endif #endif diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.c b/src/jdk.jdwp.agent/share/native/libjdwp/util.c index 0bb7c8837d8..7e198be9a46 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c @@ -1984,8 +1984,6 @@ eventIndex2jvmti(EventIndex ei) return event; } -#ifdef DEBUG - char* eventIndex2EventName(EventIndex ei) { @@ -2040,8 +2038,6 @@ eventIndex2EventName(EventIndex ei) } } -#endif - EventIndex jdwp2EventIndex(jdwpEvent eventType) { diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.h b/src/jdk.jdwp.agent/share/native/libjdwp/util.h index c5b8a2b5f51..75281813709 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.h @@ -90,6 +90,7 @@ typedef struct { jboolean doerrorexit; jboolean modifiedUtf8; jboolean quiet; + jboolean jvmti_data_dump; /* If true, then support JVMTI DATA_DUMP_REQUEST events. */ /* Debug flags (bit mask) */ int debugflags; @@ -389,9 +390,7 @@ void *jvmtiAllocate(jint numBytes); void jvmtiDeallocate(void *buffer); void eventIndexInit(void); -#ifdef DEBUG char* eventIndex2EventName(EventIndex ei); -#endif jdwpEvent eventIndex2jdwp(EventIndex i); jvmtiEvent eventIndex2jvmti(EventIndex i); EventIndex jdwp2EventIndex(jdwpEvent eventType); diff --git a/test/jdk/com/sun/jdi/DataDumpTest.java b/test/jdk/com/sun/jdi/DataDumpTest.java new file mode 100644 index 00000000000..f46d0d5de4f --- /dev/null +++ b/test/jdk/com/sun/jdi/DataDumpTest.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import jdk.test.lib.dcmd.PidJcmdExecutor; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import com.sun.jdi.Bootstrap; +import com.sun.jdi.ClassType; +import com.sun.jdi.VirtualMachine; +import com.sun.jdi.VMDisconnectedException; +import com.sun.jdi.connect.AttachingConnector; +import com.sun.jdi.connect.Connector; +import com.sun.jdi.connect.IllegalConnectorArgumentsException; +import com.sun.jdi.event.ClassPrepareEvent; +import com.sun.jdi.event.Event; +import com.sun.jdi.event.EventSet; +import com.sun.jdi.request.EventRequest; +import com.sun.jdi.request.ClassPrepareRequest; + +/** + * @test + * @bug 8332488 + * @summary Unit test for testing debug agent support for JVMTI.data_dump jcmd. + * + * @library /test/lib + * @modules jdk.jdi + * @run driver DataDumpTest + */ + +class DataDumpTestTarg { + public static void main(String args[]) throws Exception { + // Write something that can be read by the driver + System.out.println("Debuggee started"); + } +} + +public class DataDumpTest { + + public static void main(String[] args) throws Exception { + System.out.println("Test 1: Debuggee start with datadump=y"); + runTest("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,datadump=y"); + } + + private static void sleep(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + } + } + + private static void runTest(String jdwpArg) throws Exception { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + jdwpArg, + // Probably not required by this test, but best to include when using datadump + "-XX:+StartAttachListener", + "DataDumpTestTarg"); + Process p = null; + OutputAnalyzer out = null; + try { + p = pb.start(); + InputStream is = p.getInputStream(); + out = new OutputAnalyzer(p); + + // Attach a debugger and do the data dump. The data dump output will appear + // in the debuggee output. + attachAndDump(p.pid()); + + out.waitFor(); // Wait for the debuggee to exit + + System.out.println("Deuggee output:"); + System.out.println(out.getOutput()); + + // All these strings are part of the debug agent data dump output. + out.shouldHaveExitValue(0); + out.shouldContain("Debuggee started"); + out.shouldContain("Debug Agent Data Dump"); + out.shouldContain("suspendAllCount: 0"); + out.shouldContain("ClassMatch: classPattern(DataDumpTestTarg)"); + out.shouldContain("Handlers for EI_VM_DEATH"); + } finally { + if (p != null) { + p.destroyForcibly(); + } + } + } + + private static void attachAndDump(long pid) throws IOException, + IllegalConnectorArgumentsException { + // Get the ProcessAttachingConnector, which can attach using the pid of the debuggee. + AttachingConnector ac = Bootstrap.virtualMachineManager().attachingConnectors() + .stream() + .filter(c -> c.name().equals("com.sun.jdi.ProcessAttach")) + .findFirst() + .orElseThrow(() -> new RuntimeException("Unable to locate ProcessAttachingConnector")); + + // Set the connector's "pid" argument to the pid of the debuggee. + Map args = ac.defaultArguments(); + Connector.StringArgument arg = (Connector.StringArgument)args.get("pid"); + arg.setValue("" + pid); + + // Attach to the debuggee. + System.out.println("Debugger is attaching to: " + pid + " ..."); + VirtualMachine vm = ac.attach(args); + + // List all threads as a sanity check. + System.out.println("Attached! Now listing threads ..."); + vm.allThreads().stream().forEach(System.out::println); + + // Request VM to trigger ClassPrepareRequest when DataDumpTestTarg class is prepared. + ClassPrepareRequest classPrepareRequest = vm.eventRequestManager().createClassPrepareRequest(); + classPrepareRequest.addClassFilter("DataDumpTestTarg"); + // Don't use SUSPEND_ALL here. That might prevent the data dump because the + // Signal Dispatcher and Attach Listener threads will be suspended, and they + // may be needed by the jcmd support. + classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD); + classPrepareRequest.enable(); + + try { + while (true) { // Exit when we get VMDisconnectedException + EventSet eventSet = vm.eventQueue().remove(); + if (eventSet == null) { + continue; + } + for (Event event : eventSet) { + System.out.println("Received event: " + event); + if (event instanceof ClassPrepareEvent) { + ClassPrepareEvent evt = (ClassPrepareEvent) event; + ClassType classType = (ClassType) evt.referenceType(); + + // Run JVMTI.data_dump jcmd. + OutputAnalyzer out = new PidJcmdExecutor("" + pid).execute("JVMTI.data_dump"); + out.waitFor(); + + // Verify the output of the jcmd. Note the actual dump is in the debuggee + // output, not in the jcmd output, so we don't check it here. + System.out.println("JVMTI.data_dump output:"); + System.out.println(out.getOutput()); + out.shouldContain("Command executed successfully"); + out.shouldHaveExitValue(0); + } + } + eventSet.resume(); + } + } catch (VMDisconnectedException e) { + System.out.println("VM is now disconnected."); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } +} From aff7936ff088249d1fc787a9f9ef687f987f556c Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 14 Aug 2024 18:42:59 +0000 Subject: [PATCH 81/84] 8338333: Add jls links to javax.lang.model.element.Modifier Reviewed-by: liach, iris, prappo, vromero, jlahoda --- .../javax/lang/model/element/Modifier.java | 106 ++++++++++++++++-- 1 file changed, 94 insertions(+), 12 deletions(-) diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java b/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java index 9dcd8390b60..da0195b6cf2 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,25 +51,68 @@ public enum Modifier { // Note java.lang.reflect.Modifier includes INTERFACE, but that's a VMism. - /** The modifier {@code public} */ PUBLIC, - /** The modifier {@code protected} */ PROTECTED, - /** The modifier {@code private} */ PRIVATE, - /** The modifier {@code abstract} */ ABSTRACT, + /** + * The modifier {@code public} + * + * @jls 6.6 Access Control + */ + PUBLIC, + + /** + * The modifier {@code protected} + * + * @jls 6.6 Access Control + */ + PROTECTED, + + /** + * The modifier {@code private} + * + * @jls 6.6 Access Control + */ + PRIVATE, + + /** + * The modifier {@code abstract} + * + * @jls 8.1.1.1 {@code abstract} Classes + * @jls 8.4.3.1 {@code abstract} Methods + * @jls 9.1.1.1 {@code abstract} Interfaces + */ + ABSTRACT, + /** * The modifier {@code default} + * + * @jls 9.4 Method Declarations * @since 1.8 */ DEFAULT, - /** The modifier {@code static} */ STATIC, + + /** + * The modifier {@code static} + * + * @jls 8.1.1.4 {@code static} Classes + * @jls 8.3.1.1 {@code static} Fields + * @jls 8.4.3.2 {@code static} Methods + * @jls 9.1.1.3 {@code static} Interfaces + */ + STATIC, /** * The modifier {@code sealed} + * + * @jls 8.1.1.2 {@code sealed}, {@code non-sealed}, and {@code final} Classes + * @jls 9.1.1.4 {@code sealed} and {@code non-sealed} Interfaces * @since 17 */ SEALED, /** * The modifier {@code non-sealed} + * + * @jls 8.1.1.2 {@code sealed}, {@code non-sealed}, and {@code final} Classes + * @jls 9.1.1.4 {@code sealed} and {@code non-sealed} Interfaces * @since 17 */ NON_SEALED { @@ -77,12 +120,51 @@ public String toString() { return "non-sealed"; } }, - /** The modifier {@code final} */ FINAL, - /** The modifier {@code transient} */ TRANSIENT, - /** The modifier {@code volatile} */ VOLATILE, - /** The modifier {@code synchronized} */ SYNCHRONIZED, - /** The modifier {@code native} */ NATIVE, - /** The modifier {@code strictfp} */ STRICTFP; + /** + * The modifier {@code final} + * + * @jls 8.1.1.2 {@code sealed}, {@code non-sealed}, and {@code final} Classes + * @jls 8.3.1.2 {@code final} Fields + * @jls 8.4.3.3 {@code final} Methods + */ + FINAL, + + /** + * The modifier {@code transient} + * + * @jls 8.3.1.3 {@code transient} Fields + */ + TRANSIENT, + + /** + * The modifier {@code volatile} + * + * @jls 8.3.1.4 {@code volatile} Fields + */ + VOLATILE, + + /** + * The modifier {@code synchronized} + * + * @jls 8.4.3.6 {@code synchronized} Methods + */ + SYNCHRONIZED, + + /** + * The modifier {@code native} + * + * @jls 8.4.3.4 {@code native} Methods + */ + NATIVE, + + /** + * The modifier {@code strictfp} + * + * @jls 8.1.1.3 {@code strictfp} Classes + * @jls 8.4.3.5 {@code strictfp} Methods + * @jls 9.1.1.2 {@code strictfp} Interfaces + */ + STRICTFP; /** * Returns this modifier's name as defined in The From e3a5e265a7747b02b8f828fbedea0dda7246fc51 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Wed, 14 Aug 2024 18:55:58 +0000 Subject: [PATCH 82/84] 8338344: Test TestPrivilegedMode.java intermittent fails java.lang.NoClassDefFoundError: jdk/test/lib/Platform Reviewed-by: chagedorn, shade --- .../jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java index 8c168b73260..feb8fe9e530 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,7 +100,7 @@ private void prepareTestVMFlags(List additionalFlags, TestFrameworkSocke String bootClassPath = "-Xbootclasspath/a:."; if (testClassesOnBootClassPath) { // Add test classes themselves to boot classpath to make them privileged. - bootClassPath += File.pathSeparator + Utils.TEST_CLASSES; + bootClassPath += File.pathSeparator + Utils.TEST_CLASS_PATH; } cmds.add(bootClassPath); cmds.add("-XX:+UnlockDiagnosticVMOptions"); From 4669e7b7b02636a8bd7381a9d401aaaf0c1d7294 Mon Sep 17 00:00:00 2001 From: Evgeny Nikitin Date: Thu, 15 Aug 2024 05:36:11 +0000 Subject: [PATCH 83/84] 8337102: JITTester: Fix breaks in static initialization blocks Reviewed-by: kvn, iveresov --- .../jtreg/testlibrary/jittester/conf/default.properties | 2 +- .../factories/StaticConstructorDefinitionFactory.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties index cd559e59120..4b0bb7bd334 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties +++ b/test/hotspot/jtreg/testlibrary/jittester/conf/default.properties @@ -8,6 +8,6 @@ classes-file=conf/classes.lst exclude-methods-file=conf/exclude.methods.lst print-complexity=true print-hierarchy=true -disable-static=true +disable-static=false generatorsFactories=jdk.test.lib.jittester.TestGeneratorsFactory generators=JavaCode,ByteCode diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java index 0a77fbb7d2c..0354559bf67 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java +++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/factories/StaticConstructorDefinitionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ public StaticConstructorDefinition produce() throws ProductionFailedException { .setOperatorLimit(operatorLimit) .setLevel(level) .setSubBlock(true) - .setCanHaveBreaks(true) + .setCanHaveBreaks(false) .setCanHaveContinues(false) .setCanHaveReturn(false) .getBlockFactory() From 4c344335fe0abc04308f4bfc62c6b3afc110240c Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 15 Aug 2024 07:39:31 +0000 Subject: [PATCH 84/84] 8338304: clang on Linux - check for lld presence after JDK-8333189 Reviewed-by: erikj, ihse --- make/autoconf/flags-ldflags.m4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index a2d0d4e606a..fab8bec789b 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -71,7 +71,9 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], LDFLAGS_CXX_PARTIAL_LINKING="$MACHINE_FLAG -r" if test "x$OPENJDK_TARGET_OS" = xlinux; then + # Clang needs the lld linker to work correctly BASIC_LDFLAGS="-fuse-ld=lld -Wl,--exclude-libs,ALL" + UTIL_REQUIRE_PROGS(LLD, lld) fi if test "x$OPENJDK_TARGET_OS" = xaix; then BASIC_LDFLAGS="-Wl,-b64 -Wl,-brtl -Wl,-bnorwexec -Wl,-bnolibpath -Wl,-bnoexpall \